Merge "Add additional logs for bootanimation"
diff --git a/Android.bp b/Android.bp
index 60ec7e2..9d48cf8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -97,7 +97,7 @@
":platform-compat-native-aidl",
// AIDL sources from external directories
- ":android.hardware.security.keymint-V1-java-source",
+ ":android.hardware.security.keymint-V2-java-source",
":android.hardware.security.secureclock-V1-java-source",
":android.security.apc-java-source",
":android.security.authorization-java-source",
@@ -140,21 +140,8 @@
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",
@@ -188,7 +175,6 @@
"sax/java",
"telecomm/java",
- "apex/media/aidl/stable",
// TODO(b/147699819): remove this
"telephony/java",
],
@@ -284,7 +270,10 @@
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",
+ "packages/modules/Media/apex/aidl/stable",
],
},
dxflags: [
@@ -409,7 +398,6 @@
// 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",
@@ -461,21 +449,28 @@
}
// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
-metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
- "--hide-package com.android.server " +
- "--hide-package android.audio.policy.configuration.V7_0 " +
- "--error UnhiddenSystemApi " +
- "--hide RequiresPermission " +
- "--hide CallbackInterface " +
- "--hide MissingPermission --hide BroadcastBehavior " +
- "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
- "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
- "--error NoSettingsProvider " +
- "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
+metalava_framework_docs_args = "" +
"--api-lint-ignore-prefix android.icu. " +
"--api-lint-ignore-prefix java. " +
"--api-lint-ignore-prefix junit. " +
- "--api-lint-ignore-prefix org. "
+ "--api-lint-ignore-prefix org. " +
+ "--error NoSettingsProvider " +
+ "--error UnhiddenSystemApi " +
+ "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
+ "--hide BroadcastBehavior " +
+ "--hide CallbackInterface " +
+ "--hide DeprecationMismatch " +
+ "--hide HiddenSuperclass " +
+ "--hide HiddenTypeParameter " +
+ "--hide MissingPermission " +
+ "--hide-package android.audio.policy.configuration.V7_0 " +
+ "--hide-package com.android.server " +
+ "--hide RequiresPermission " +
+ "--hide SdkConstant " +
+ "--hide Todo " +
+ "--hide Typo " +
+ "--hide UnavailableSymbol " +
+ "--manifest $(location core/res/AndroidManifest.xml) "
packages_to_document = [
"android",
@@ -521,6 +516,9 @@
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)
@@ -558,16 +556,15 @@
stubs_defaults {
name: "module-classpath-stubs-defaults",
aidl: {
- local_include_dirs: [
- "apex/media/aidl/stable",
- ],
include_dirs: [
"packages/modules/Connectivity/framework/aidl-export",
+ "packages/modules/Media/apex/aidl/stable",
],
},
libs: [
"art.module.public.api",
"sdk_module-lib_current_framework-tethering",
+ "sdk_module-lib_current_framework-connectivity-t",
"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
diff --git a/Android.mk b/Android.mk
index 46529eb..d9e202c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,6 +15,14 @@
#
LOCAL_PATH := $(call my-dir)
+$(eval $(call declare-1p-copy-files,frameworks/base,.ogg))
+$(eval $(call declare-1p-copy-files,frameworks/base,.kl))
+$(eval $(call declare-1p-copy-files,frameworks/base,.kcm))
+$(eval $(call declare-1p-copy-files,frameworks/base,.idc))
+$(eval $(call declare-1p-copy-files,frameworks/base,dirty-image-objects))
+$(eval $(call declare-1p-copy-files,frameworks/base/config,))
+$(eval $(call declare-1p-copy-files,frameworks/native/data,))
+
# Load framework-specific path mappings used later in the build.
include $(LOCAL_PATH)/pathmap.mk
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 5595e95..2efeab6 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -140,11 +140,9 @@
"api-versions-jars-dir",
],
aidl: {
- local_include_dirs: [
- "apex/media/aidl/stable",
- ],
include_dirs: [
"packages/modules/Connectivity/framework/aidl-export",
+ "packages/modules/Media/apex/aidl/stable",
],
},
}
diff --git a/INPUT_OWNERS b/INPUT_OWNERS
new file mode 100644
index 0000000..6041f637f
--- /dev/null
+++ b/INPUT_OWNERS
@@ -0,0 +1,3 @@
+michaelwr@google.com
+prabirmsp@google.com
+svv@google.com
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 5cb0a78..fef95e8 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -250,6 +250,7 @@
srcs: [":module-lib-api-stubs-docs-non-updatable"],
libs: [
"sdk_module-lib_current_framework-tethering",
+ "sdk_module-lib_current_framework-connectivity-t",
"sdk_public_current_framework-bluetooth",
// NOTE: The below can be removed once the prebuilt stub contains bluetooth.
"sdk_system_current_android",
@@ -365,6 +366,64 @@
},
}
+////////////////////////////////////////////////////////////////////////
+// api-versions.xml generation, for public and system. This API database
+// also contains the android.test.* APIs.
+////////////////////////////////////////////////////////////////////////
+
+java_library {
+ name: "android_stubs_current_with_test_libs",
+ static_libs: [
+ "android_stubs_current",
+ "android.test.base.stubs",
+ "android.test.mock.stubs",
+ "android.test.runner.stubs",
+ ],
+ defaults: ["android.jar_defaults"],
+ visibility: [
+ "//visibility:override",
+ "//visibility:private",
+ ],
+}
+
+java_library {
+ name: "android_system_stubs_current_with_test_libs",
+ static_libs: [
+ "android_system_stubs_current",
+ "android.test.base.stubs.system",
+ "android.test.mock.stubs.system",
+ "android.test.runner.stubs.system",
+ ],
+ defaults: ["android.jar_defaults"],
+ visibility: [
+ "//visibility:override",
+ "//visibility:private",
+ ],
+}
+
+droidstubs {
+ name: "api_versions_public",
+ srcs: [":android_stubs_current_with_test_libs{.jar}"],
+ generate_stubs: false,
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+}
+
+droidstubs {
+ name: "api_versions_system",
+ srcs: [":android_system_stubs_current_with_test_libs{.jar}"],
+ generate_stubs: false,
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ api_levels_sdk_type: "system",
+}
+
/////////////////////////////////////////////////////////////////////
// hwbinder.stubs provides APIs required for building HIDL Java
// libraries.
diff --git a/apct-tests/perftests/core/OWNERS b/apct-tests/perftests/core/OWNERS
index 18486af..2b3564e 100644
--- a/apct-tests/perftests/core/OWNERS
+++ b/apct-tests/perftests/core/OWNERS
@@ -1 +1,5 @@
include /graphics/java/android/graphics/fonts/OWNERS
+
+# Bug component: 568761
+per-file /apct-tests/perftests/core/res/* = felkachang@google.com,zyy@google.com
+
diff --git a/apct-tests/perftests/core/res/values/colors.xml b/apct-tests/perftests/core/res/values/colors.xml
new file mode 100644
index 0000000..5e56c25
--- /dev/null
+++ b/apct-tests/perftests/core/res/values/colors.xml
@@ -0,0 +1,10022 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources>
+ <!--- The colors with prefix "i_am_color_%x" and %x is from 0 to 10000. They are used by
+ ResourcesPerfTest.java -->
+ <color name="i_am_color_0">#00000000</color>
+ <color name="i_am_color_1">#00000001</color>
+ <color name="i_am_color_2">#00000002</color>
+ <color name="i_am_color_3">#00000003</color>
+ <color name="i_am_color_4">#00000004</color>
+ <color name="i_am_color_5">#00000005</color>
+ <color name="i_am_color_6">#00000006</color>
+ <color name="i_am_color_7">#00000007</color>
+ <color name="i_am_color_8">#00000008</color>
+ <color name="i_am_color_9">#00000009</color>
+ <color name="i_am_color_a">#0000000a</color>
+ <color name="i_am_color_b">#0000000b</color>
+ <color name="i_am_color_c">#0000000c</color>
+ <color name="i_am_color_d">#0000000d</color>
+ <color name="i_am_color_e">#0000000e</color>
+ <color name="i_am_color_f">#0000000f</color>
+ <color name="i_am_color_10">#00000010</color>
+ <color name="i_am_color_11">#00000011</color>
+ <color name="i_am_color_12">#00000012</color>
+ <color name="i_am_color_13">#00000013</color>
+ <color name="i_am_color_14">#00000014</color>
+ <color name="i_am_color_15">#00000015</color>
+ <color name="i_am_color_16">#00000016</color>
+ <color name="i_am_color_17">#00000017</color>
+ <color name="i_am_color_18">#00000018</color>
+ <color name="i_am_color_19">#00000019</color>
+ <color name="i_am_color_1a">#0000001a</color>
+ <color name="i_am_color_1b">#0000001b</color>
+ <color name="i_am_color_1c">#0000001c</color>
+ <color name="i_am_color_1d">#0000001d</color>
+ <color name="i_am_color_1e">#0000001e</color>
+ <color name="i_am_color_1f">#0000001f</color>
+ <color name="i_am_color_20">#00000020</color>
+ <color name="i_am_color_21">#00000021</color>
+ <color name="i_am_color_22">#00000022</color>
+ <color name="i_am_color_23">#00000023</color>
+ <color name="i_am_color_24">#00000024</color>
+ <color name="i_am_color_25">#00000025</color>
+ <color name="i_am_color_26">#00000026</color>
+ <color name="i_am_color_27">#00000027</color>
+ <color name="i_am_color_28">#00000028</color>
+ <color name="i_am_color_29">#00000029</color>
+ <color name="i_am_color_2a">#0000002a</color>
+ <color name="i_am_color_2b">#0000002b</color>
+ <color name="i_am_color_2c">#0000002c</color>
+ <color name="i_am_color_2d">#0000002d</color>
+ <color name="i_am_color_2e">#0000002e</color>
+ <color name="i_am_color_2f">#0000002f</color>
+ <color name="i_am_color_30">#00000030</color>
+ <color name="i_am_color_31">#00000031</color>
+ <color name="i_am_color_32">#00000032</color>
+ <color name="i_am_color_33">#00000033</color>
+ <color name="i_am_color_34">#00000034</color>
+ <color name="i_am_color_35">#00000035</color>
+ <color name="i_am_color_36">#00000036</color>
+ <color name="i_am_color_37">#00000037</color>
+ <color name="i_am_color_38">#00000038</color>
+ <color name="i_am_color_39">#00000039</color>
+ <color name="i_am_color_3a">#0000003a</color>
+ <color name="i_am_color_3b">#0000003b</color>
+ <color name="i_am_color_3c">#0000003c</color>
+ <color name="i_am_color_3d">#0000003d</color>
+ <color name="i_am_color_3e">#0000003e</color>
+ <color name="i_am_color_3f">#0000003f</color>
+ <color name="i_am_color_40">#00000040</color>
+ <color name="i_am_color_41">#00000041</color>
+ <color name="i_am_color_42">#00000042</color>
+ <color name="i_am_color_43">#00000043</color>
+ <color name="i_am_color_44">#00000044</color>
+ <color name="i_am_color_45">#00000045</color>
+ <color name="i_am_color_46">#00000046</color>
+ <color name="i_am_color_47">#00000047</color>
+ <color name="i_am_color_48">#00000048</color>
+ <color name="i_am_color_49">#00000049</color>
+ <color name="i_am_color_4a">#0000004a</color>
+ <color name="i_am_color_4b">#0000004b</color>
+ <color name="i_am_color_4c">#0000004c</color>
+ <color name="i_am_color_4d">#0000004d</color>
+ <color name="i_am_color_4e">#0000004e</color>
+ <color name="i_am_color_4f">#0000004f</color>
+ <color name="i_am_color_50">#00000050</color>
+ <color name="i_am_color_51">#00000051</color>
+ <color name="i_am_color_52">#00000052</color>
+ <color name="i_am_color_53">#00000053</color>
+ <color name="i_am_color_54">#00000054</color>
+ <color name="i_am_color_55">#00000055</color>
+ <color name="i_am_color_56">#00000056</color>
+ <color name="i_am_color_57">#00000057</color>
+ <color name="i_am_color_58">#00000058</color>
+ <color name="i_am_color_59">#00000059</color>
+ <color name="i_am_color_5a">#0000005a</color>
+ <color name="i_am_color_5b">#0000005b</color>
+ <color name="i_am_color_5c">#0000005c</color>
+ <color name="i_am_color_5d">#0000005d</color>
+ <color name="i_am_color_5e">#0000005e</color>
+ <color name="i_am_color_5f">#0000005f</color>
+ <color name="i_am_color_60">#00000060</color>
+ <color name="i_am_color_61">#00000061</color>
+ <color name="i_am_color_62">#00000062</color>
+ <color name="i_am_color_63">#00000063</color>
+ <color name="i_am_color_64">#00000064</color>
+ <color name="i_am_color_65">#00000065</color>
+ <color name="i_am_color_66">#00000066</color>
+ <color name="i_am_color_67">#00000067</color>
+ <color name="i_am_color_68">#00000068</color>
+ <color name="i_am_color_69">#00000069</color>
+ <color name="i_am_color_6a">#0000006a</color>
+ <color name="i_am_color_6b">#0000006b</color>
+ <color name="i_am_color_6c">#0000006c</color>
+ <color name="i_am_color_6d">#0000006d</color>
+ <color name="i_am_color_6e">#0000006e</color>
+ <color name="i_am_color_6f">#0000006f</color>
+ <color name="i_am_color_70">#00000070</color>
+ <color name="i_am_color_71">#00000071</color>
+ <color name="i_am_color_72">#00000072</color>
+ <color name="i_am_color_73">#00000073</color>
+ <color name="i_am_color_74">#00000074</color>
+ <color name="i_am_color_75">#00000075</color>
+ <color name="i_am_color_76">#00000076</color>
+ <color name="i_am_color_77">#00000077</color>
+ <color name="i_am_color_78">#00000078</color>
+ <color name="i_am_color_79">#00000079</color>
+ <color name="i_am_color_7a">#0000007a</color>
+ <color name="i_am_color_7b">#0000007b</color>
+ <color name="i_am_color_7c">#0000007c</color>
+ <color name="i_am_color_7d">#0000007d</color>
+ <color name="i_am_color_7e">#0000007e</color>
+ <color name="i_am_color_7f">#0000007f</color>
+ <color name="i_am_color_80">#00000080</color>
+ <color name="i_am_color_81">#00000081</color>
+ <color name="i_am_color_82">#00000082</color>
+ <color name="i_am_color_83">#00000083</color>
+ <color name="i_am_color_84">#00000084</color>
+ <color name="i_am_color_85">#00000085</color>
+ <color name="i_am_color_86">#00000086</color>
+ <color name="i_am_color_87">#00000087</color>
+ <color name="i_am_color_88">#00000088</color>
+ <color name="i_am_color_89">#00000089</color>
+ <color name="i_am_color_8a">#0000008a</color>
+ <color name="i_am_color_8b">#0000008b</color>
+ <color name="i_am_color_8c">#0000008c</color>
+ <color name="i_am_color_8d">#0000008d</color>
+ <color name="i_am_color_8e">#0000008e</color>
+ <color name="i_am_color_8f">#0000008f</color>
+ <color name="i_am_color_90">#00000090</color>
+ <color name="i_am_color_91">#00000091</color>
+ <color name="i_am_color_92">#00000092</color>
+ <color name="i_am_color_93">#00000093</color>
+ <color name="i_am_color_94">#00000094</color>
+ <color name="i_am_color_95">#00000095</color>
+ <color name="i_am_color_96">#00000096</color>
+ <color name="i_am_color_97">#00000097</color>
+ <color name="i_am_color_98">#00000098</color>
+ <color name="i_am_color_99">#00000099</color>
+ <color name="i_am_color_9a">#0000009a</color>
+ <color name="i_am_color_9b">#0000009b</color>
+ <color name="i_am_color_9c">#0000009c</color>
+ <color name="i_am_color_9d">#0000009d</color>
+ <color name="i_am_color_9e">#0000009e</color>
+ <color name="i_am_color_9f">#0000009f</color>
+ <color name="i_am_color_a0">#000000a0</color>
+ <color name="i_am_color_a1">#000000a1</color>
+ <color name="i_am_color_a2">#000000a2</color>
+ <color name="i_am_color_a3">#000000a3</color>
+ <color name="i_am_color_a4">#000000a4</color>
+ <color name="i_am_color_a5">#000000a5</color>
+ <color name="i_am_color_a6">#000000a6</color>
+ <color name="i_am_color_a7">#000000a7</color>
+ <color name="i_am_color_a8">#000000a8</color>
+ <color name="i_am_color_a9">#000000a9</color>
+ <color name="i_am_color_aa">#000000aa</color>
+ <color name="i_am_color_ab">#000000ab</color>
+ <color name="i_am_color_ac">#000000ac</color>
+ <color name="i_am_color_ad">#000000ad</color>
+ <color name="i_am_color_ae">#000000ae</color>
+ <color name="i_am_color_af">#000000af</color>
+ <color name="i_am_color_b0">#000000b0</color>
+ <color name="i_am_color_b1">#000000b1</color>
+ <color name="i_am_color_b2">#000000b2</color>
+ <color name="i_am_color_b3">#000000b3</color>
+ <color name="i_am_color_b4">#000000b4</color>
+ <color name="i_am_color_b5">#000000b5</color>
+ <color name="i_am_color_b6">#000000b6</color>
+ <color name="i_am_color_b7">#000000b7</color>
+ <color name="i_am_color_b8">#000000b8</color>
+ <color name="i_am_color_b9">#000000b9</color>
+ <color name="i_am_color_ba">#000000ba</color>
+ <color name="i_am_color_bb">#000000bb</color>
+ <color name="i_am_color_bc">#000000bc</color>
+ <color name="i_am_color_bd">#000000bd</color>
+ <color name="i_am_color_be">#000000be</color>
+ <color name="i_am_color_bf">#000000bf</color>
+ <color name="i_am_color_c0">#000000c0</color>
+ <color name="i_am_color_c1">#000000c1</color>
+ <color name="i_am_color_c2">#000000c2</color>
+ <color name="i_am_color_c3">#000000c3</color>
+ <color name="i_am_color_c4">#000000c4</color>
+ <color name="i_am_color_c5">#000000c5</color>
+ <color name="i_am_color_c6">#000000c6</color>
+ <color name="i_am_color_c7">#000000c7</color>
+ <color name="i_am_color_c8">#000000c8</color>
+ <color name="i_am_color_c9">#000000c9</color>
+ <color name="i_am_color_ca">#000000ca</color>
+ <color name="i_am_color_cb">#000000cb</color>
+ <color name="i_am_color_cc">#000000cc</color>
+ <color name="i_am_color_cd">#000000cd</color>
+ <color name="i_am_color_ce">#000000ce</color>
+ <color name="i_am_color_cf">#000000cf</color>
+ <color name="i_am_color_d0">#000000d0</color>
+ <color name="i_am_color_d1">#000000d1</color>
+ <color name="i_am_color_d2">#000000d2</color>
+ <color name="i_am_color_d3">#000000d3</color>
+ <color name="i_am_color_d4">#000000d4</color>
+ <color name="i_am_color_d5">#000000d5</color>
+ <color name="i_am_color_d6">#000000d6</color>
+ <color name="i_am_color_d7">#000000d7</color>
+ <color name="i_am_color_d8">#000000d8</color>
+ <color name="i_am_color_d9">#000000d9</color>
+ <color name="i_am_color_da">#000000da</color>
+ <color name="i_am_color_db">#000000db</color>
+ <color name="i_am_color_dc">#000000dc</color>
+ <color name="i_am_color_dd">#000000dd</color>
+ <color name="i_am_color_de">#000000de</color>
+ <color name="i_am_color_df">#000000df</color>
+ <color name="i_am_color_e0">#000000e0</color>
+ <color name="i_am_color_e1">#000000e1</color>
+ <color name="i_am_color_e2">#000000e2</color>
+ <color name="i_am_color_e3">#000000e3</color>
+ <color name="i_am_color_e4">#000000e4</color>
+ <color name="i_am_color_e5">#000000e5</color>
+ <color name="i_am_color_e6">#000000e6</color>
+ <color name="i_am_color_e7">#000000e7</color>
+ <color name="i_am_color_e8">#000000e8</color>
+ <color name="i_am_color_e9">#000000e9</color>
+ <color name="i_am_color_ea">#000000ea</color>
+ <color name="i_am_color_eb">#000000eb</color>
+ <color name="i_am_color_ec">#000000ec</color>
+ <color name="i_am_color_ed">#000000ed</color>
+ <color name="i_am_color_ee">#000000ee</color>
+ <color name="i_am_color_ef">#000000ef</color>
+ <color name="i_am_color_f0">#000000f0</color>
+ <color name="i_am_color_f1">#000000f1</color>
+ <color name="i_am_color_f2">#000000f2</color>
+ <color name="i_am_color_f3">#000000f3</color>
+ <color name="i_am_color_f4">#000000f4</color>
+ <color name="i_am_color_f5">#000000f5</color>
+ <color name="i_am_color_f6">#000000f6</color>
+ <color name="i_am_color_f7">#000000f7</color>
+ <color name="i_am_color_f8">#000000f8</color>
+ <color name="i_am_color_f9">#000000f9</color>
+ <color name="i_am_color_fa">#000000fa</color>
+ <color name="i_am_color_fb">#000000fb</color>
+ <color name="i_am_color_fc">#000000fc</color>
+ <color name="i_am_color_fd">#000000fd</color>
+ <color name="i_am_color_fe">#000000fe</color>
+ <color name="i_am_color_ff">#000000ff</color>
+ <color name="i_am_color_100">#00000100</color>
+ <color name="i_am_color_101">#00000101</color>
+ <color name="i_am_color_102">#00000102</color>
+ <color name="i_am_color_103">#00000103</color>
+ <color name="i_am_color_104">#00000104</color>
+ <color name="i_am_color_105">#00000105</color>
+ <color name="i_am_color_106">#00000106</color>
+ <color name="i_am_color_107">#00000107</color>
+ <color name="i_am_color_108">#00000108</color>
+ <color name="i_am_color_109">#00000109</color>
+ <color name="i_am_color_10a">#0000010a</color>
+ <color name="i_am_color_10b">#0000010b</color>
+ <color name="i_am_color_10c">#0000010c</color>
+ <color name="i_am_color_10d">#0000010d</color>
+ <color name="i_am_color_10e">#0000010e</color>
+ <color name="i_am_color_10f">#0000010f</color>
+ <color name="i_am_color_110">#00000110</color>
+ <color name="i_am_color_111">#00000111</color>
+ <color name="i_am_color_112">#00000112</color>
+ <color name="i_am_color_113">#00000113</color>
+ <color name="i_am_color_114">#00000114</color>
+ <color name="i_am_color_115">#00000115</color>
+ <color name="i_am_color_116">#00000116</color>
+ <color name="i_am_color_117">#00000117</color>
+ <color name="i_am_color_118">#00000118</color>
+ <color name="i_am_color_119">#00000119</color>
+ <color name="i_am_color_11a">#0000011a</color>
+ <color name="i_am_color_11b">#0000011b</color>
+ <color name="i_am_color_11c">#0000011c</color>
+ <color name="i_am_color_11d">#0000011d</color>
+ <color name="i_am_color_11e">#0000011e</color>
+ <color name="i_am_color_11f">#0000011f</color>
+ <color name="i_am_color_120">#00000120</color>
+ <color name="i_am_color_121">#00000121</color>
+ <color name="i_am_color_122">#00000122</color>
+ <color name="i_am_color_123">#00000123</color>
+ <color name="i_am_color_124">#00000124</color>
+ <color name="i_am_color_125">#00000125</color>
+ <color name="i_am_color_126">#00000126</color>
+ <color name="i_am_color_127">#00000127</color>
+ <color name="i_am_color_128">#00000128</color>
+ <color name="i_am_color_129">#00000129</color>
+ <color name="i_am_color_12a">#0000012a</color>
+ <color name="i_am_color_12b">#0000012b</color>
+ <color name="i_am_color_12c">#0000012c</color>
+ <color name="i_am_color_12d">#0000012d</color>
+ <color name="i_am_color_12e">#0000012e</color>
+ <color name="i_am_color_12f">#0000012f</color>
+ <color name="i_am_color_130">#00000130</color>
+ <color name="i_am_color_131">#00000131</color>
+ <color name="i_am_color_132">#00000132</color>
+ <color name="i_am_color_133">#00000133</color>
+ <color name="i_am_color_134">#00000134</color>
+ <color name="i_am_color_135">#00000135</color>
+ <color name="i_am_color_136">#00000136</color>
+ <color name="i_am_color_137">#00000137</color>
+ <color name="i_am_color_138">#00000138</color>
+ <color name="i_am_color_139">#00000139</color>
+ <color name="i_am_color_13a">#0000013a</color>
+ <color name="i_am_color_13b">#0000013b</color>
+ <color name="i_am_color_13c">#0000013c</color>
+ <color name="i_am_color_13d">#0000013d</color>
+ <color name="i_am_color_13e">#0000013e</color>
+ <color name="i_am_color_13f">#0000013f</color>
+ <color name="i_am_color_140">#00000140</color>
+ <color name="i_am_color_141">#00000141</color>
+ <color name="i_am_color_142">#00000142</color>
+ <color name="i_am_color_143">#00000143</color>
+ <color name="i_am_color_144">#00000144</color>
+ <color name="i_am_color_145">#00000145</color>
+ <color name="i_am_color_146">#00000146</color>
+ <color name="i_am_color_147">#00000147</color>
+ <color name="i_am_color_148">#00000148</color>
+ <color name="i_am_color_149">#00000149</color>
+ <color name="i_am_color_14a">#0000014a</color>
+ <color name="i_am_color_14b">#0000014b</color>
+ <color name="i_am_color_14c">#0000014c</color>
+ <color name="i_am_color_14d">#0000014d</color>
+ <color name="i_am_color_14e">#0000014e</color>
+ <color name="i_am_color_14f">#0000014f</color>
+ <color name="i_am_color_150">#00000150</color>
+ <color name="i_am_color_151">#00000151</color>
+ <color name="i_am_color_152">#00000152</color>
+ <color name="i_am_color_153">#00000153</color>
+ <color name="i_am_color_154">#00000154</color>
+ <color name="i_am_color_155">#00000155</color>
+ <color name="i_am_color_156">#00000156</color>
+ <color name="i_am_color_157">#00000157</color>
+ <color name="i_am_color_158">#00000158</color>
+ <color name="i_am_color_159">#00000159</color>
+ <color name="i_am_color_15a">#0000015a</color>
+ <color name="i_am_color_15b">#0000015b</color>
+ <color name="i_am_color_15c">#0000015c</color>
+ <color name="i_am_color_15d">#0000015d</color>
+ <color name="i_am_color_15e">#0000015e</color>
+ <color name="i_am_color_15f">#0000015f</color>
+ <color name="i_am_color_160">#00000160</color>
+ <color name="i_am_color_161">#00000161</color>
+ <color name="i_am_color_162">#00000162</color>
+ <color name="i_am_color_163">#00000163</color>
+ <color name="i_am_color_164">#00000164</color>
+ <color name="i_am_color_165">#00000165</color>
+ <color name="i_am_color_166">#00000166</color>
+ <color name="i_am_color_167">#00000167</color>
+ <color name="i_am_color_168">#00000168</color>
+ <color name="i_am_color_169">#00000169</color>
+ <color name="i_am_color_16a">#0000016a</color>
+ <color name="i_am_color_16b">#0000016b</color>
+ <color name="i_am_color_16c">#0000016c</color>
+ <color name="i_am_color_16d">#0000016d</color>
+ <color name="i_am_color_16e">#0000016e</color>
+ <color name="i_am_color_16f">#0000016f</color>
+ <color name="i_am_color_170">#00000170</color>
+ <color name="i_am_color_171">#00000171</color>
+ <color name="i_am_color_172">#00000172</color>
+ <color name="i_am_color_173">#00000173</color>
+ <color name="i_am_color_174">#00000174</color>
+ <color name="i_am_color_175">#00000175</color>
+ <color name="i_am_color_176">#00000176</color>
+ <color name="i_am_color_177">#00000177</color>
+ <color name="i_am_color_178">#00000178</color>
+ <color name="i_am_color_179">#00000179</color>
+ <color name="i_am_color_17a">#0000017a</color>
+ <color name="i_am_color_17b">#0000017b</color>
+ <color name="i_am_color_17c">#0000017c</color>
+ <color name="i_am_color_17d">#0000017d</color>
+ <color name="i_am_color_17e">#0000017e</color>
+ <color name="i_am_color_17f">#0000017f</color>
+ <color name="i_am_color_180">#00000180</color>
+ <color name="i_am_color_181">#00000181</color>
+ <color name="i_am_color_182">#00000182</color>
+ <color name="i_am_color_183">#00000183</color>
+ <color name="i_am_color_184">#00000184</color>
+ <color name="i_am_color_185">#00000185</color>
+ <color name="i_am_color_186">#00000186</color>
+ <color name="i_am_color_187">#00000187</color>
+ <color name="i_am_color_188">#00000188</color>
+ <color name="i_am_color_189">#00000189</color>
+ <color name="i_am_color_18a">#0000018a</color>
+ <color name="i_am_color_18b">#0000018b</color>
+ <color name="i_am_color_18c">#0000018c</color>
+ <color name="i_am_color_18d">#0000018d</color>
+ <color name="i_am_color_18e">#0000018e</color>
+ <color name="i_am_color_18f">#0000018f</color>
+ <color name="i_am_color_190">#00000190</color>
+ <color name="i_am_color_191">#00000191</color>
+ <color name="i_am_color_192">#00000192</color>
+ <color name="i_am_color_193">#00000193</color>
+ <color name="i_am_color_194">#00000194</color>
+ <color name="i_am_color_195">#00000195</color>
+ <color name="i_am_color_196">#00000196</color>
+ <color name="i_am_color_197">#00000197</color>
+ <color name="i_am_color_198">#00000198</color>
+ <color name="i_am_color_199">#00000199</color>
+ <color name="i_am_color_19a">#0000019a</color>
+ <color name="i_am_color_19b">#0000019b</color>
+ <color name="i_am_color_19c">#0000019c</color>
+ <color name="i_am_color_19d">#0000019d</color>
+ <color name="i_am_color_19e">#0000019e</color>
+ <color name="i_am_color_19f">#0000019f</color>
+ <color name="i_am_color_1a0">#000001a0</color>
+ <color name="i_am_color_1a1">#000001a1</color>
+ <color name="i_am_color_1a2">#000001a2</color>
+ <color name="i_am_color_1a3">#000001a3</color>
+ <color name="i_am_color_1a4">#000001a4</color>
+ <color name="i_am_color_1a5">#000001a5</color>
+ <color name="i_am_color_1a6">#000001a6</color>
+ <color name="i_am_color_1a7">#000001a7</color>
+ <color name="i_am_color_1a8">#000001a8</color>
+ <color name="i_am_color_1a9">#000001a9</color>
+ <color name="i_am_color_1aa">#000001aa</color>
+ <color name="i_am_color_1ab">#000001ab</color>
+ <color name="i_am_color_1ac">#000001ac</color>
+ <color name="i_am_color_1ad">#000001ad</color>
+ <color name="i_am_color_1ae">#000001ae</color>
+ <color name="i_am_color_1af">#000001af</color>
+ <color name="i_am_color_1b0">#000001b0</color>
+ <color name="i_am_color_1b1">#000001b1</color>
+ <color name="i_am_color_1b2">#000001b2</color>
+ <color name="i_am_color_1b3">#000001b3</color>
+ <color name="i_am_color_1b4">#000001b4</color>
+ <color name="i_am_color_1b5">#000001b5</color>
+ <color name="i_am_color_1b6">#000001b6</color>
+ <color name="i_am_color_1b7">#000001b7</color>
+ <color name="i_am_color_1b8">#000001b8</color>
+ <color name="i_am_color_1b9">#000001b9</color>
+ <color name="i_am_color_1ba">#000001ba</color>
+ <color name="i_am_color_1bb">#000001bb</color>
+ <color name="i_am_color_1bc">#000001bc</color>
+ <color name="i_am_color_1bd">#000001bd</color>
+ <color name="i_am_color_1be">#000001be</color>
+ <color name="i_am_color_1bf">#000001bf</color>
+ <color name="i_am_color_1c0">#000001c0</color>
+ <color name="i_am_color_1c1">#000001c1</color>
+ <color name="i_am_color_1c2">#000001c2</color>
+ <color name="i_am_color_1c3">#000001c3</color>
+ <color name="i_am_color_1c4">#000001c4</color>
+ <color name="i_am_color_1c5">#000001c5</color>
+ <color name="i_am_color_1c6">#000001c6</color>
+ <color name="i_am_color_1c7">#000001c7</color>
+ <color name="i_am_color_1c8">#000001c8</color>
+ <color name="i_am_color_1c9">#000001c9</color>
+ <color name="i_am_color_1ca">#000001ca</color>
+ <color name="i_am_color_1cb">#000001cb</color>
+ <color name="i_am_color_1cc">#000001cc</color>
+ <color name="i_am_color_1cd">#000001cd</color>
+ <color name="i_am_color_1ce">#000001ce</color>
+ <color name="i_am_color_1cf">#000001cf</color>
+ <color name="i_am_color_1d0">#000001d0</color>
+ <color name="i_am_color_1d1">#000001d1</color>
+ <color name="i_am_color_1d2">#000001d2</color>
+ <color name="i_am_color_1d3">#000001d3</color>
+ <color name="i_am_color_1d4">#000001d4</color>
+ <color name="i_am_color_1d5">#000001d5</color>
+ <color name="i_am_color_1d6">#000001d6</color>
+ <color name="i_am_color_1d7">#000001d7</color>
+ <color name="i_am_color_1d8">#000001d8</color>
+ <color name="i_am_color_1d9">#000001d9</color>
+ <color name="i_am_color_1da">#000001da</color>
+ <color name="i_am_color_1db">#000001db</color>
+ <color name="i_am_color_1dc">#000001dc</color>
+ <color name="i_am_color_1dd">#000001dd</color>
+ <color name="i_am_color_1de">#000001de</color>
+ <color name="i_am_color_1df">#000001df</color>
+ <color name="i_am_color_1e0">#000001e0</color>
+ <color name="i_am_color_1e1">#000001e1</color>
+ <color name="i_am_color_1e2">#000001e2</color>
+ <color name="i_am_color_1e3">#000001e3</color>
+ <color name="i_am_color_1e4">#000001e4</color>
+ <color name="i_am_color_1e5">#000001e5</color>
+ <color name="i_am_color_1e6">#000001e6</color>
+ <color name="i_am_color_1e7">#000001e7</color>
+ <color name="i_am_color_1e8">#000001e8</color>
+ <color name="i_am_color_1e9">#000001e9</color>
+ <color name="i_am_color_1ea">#000001ea</color>
+ <color name="i_am_color_1eb">#000001eb</color>
+ <color name="i_am_color_1ec">#000001ec</color>
+ <color name="i_am_color_1ed">#000001ed</color>
+ <color name="i_am_color_1ee">#000001ee</color>
+ <color name="i_am_color_1ef">#000001ef</color>
+ <color name="i_am_color_1f0">#000001f0</color>
+ <color name="i_am_color_1f1">#000001f1</color>
+ <color name="i_am_color_1f2">#000001f2</color>
+ <color name="i_am_color_1f3">#000001f3</color>
+ <color name="i_am_color_1f4">#000001f4</color>
+ <color name="i_am_color_1f5">#000001f5</color>
+ <color name="i_am_color_1f6">#000001f6</color>
+ <color name="i_am_color_1f7">#000001f7</color>
+ <color name="i_am_color_1f8">#000001f8</color>
+ <color name="i_am_color_1f9">#000001f9</color>
+ <color name="i_am_color_1fa">#000001fa</color>
+ <color name="i_am_color_1fb">#000001fb</color>
+ <color name="i_am_color_1fc">#000001fc</color>
+ <color name="i_am_color_1fd">#000001fd</color>
+ <color name="i_am_color_1fe">#000001fe</color>
+ <color name="i_am_color_1ff">#000001ff</color>
+ <color name="i_am_color_200">#00000200</color>
+ <color name="i_am_color_201">#00000201</color>
+ <color name="i_am_color_202">#00000202</color>
+ <color name="i_am_color_203">#00000203</color>
+ <color name="i_am_color_204">#00000204</color>
+ <color name="i_am_color_205">#00000205</color>
+ <color name="i_am_color_206">#00000206</color>
+ <color name="i_am_color_207">#00000207</color>
+ <color name="i_am_color_208">#00000208</color>
+ <color name="i_am_color_209">#00000209</color>
+ <color name="i_am_color_20a">#0000020a</color>
+ <color name="i_am_color_20b">#0000020b</color>
+ <color name="i_am_color_20c">#0000020c</color>
+ <color name="i_am_color_20d">#0000020d</color>
+ <color name="i_am_color_20e">#0000020e</color>
+ <color name="i_am_color_20f">#0000020f</color>
+ <color name="i_am_color_210">#00000210</color>
+ <color name="i_am_color_211">#00000211</color>
+ <color name="i_am_color_212">#00000212</color>
+ <color name="i_am_color_213">#00000213</color>
+ <color name="i_am_color_214">#00000214</color>
+ <color name="i_am_color_215">#00000215</color>
+ <color name="i_am_color_216">#00000216</color>
+ <color name="i_am_color_217">#00000217</color>
+ <color name="i_am_color_218">#00000218</color>
+ <color name="i_am_color_219">#00000219</color>
+ <color name="i_am_color_21a">#0000021a</color>
+ <color name="i_am_color_21b">#0000021b</color>
+ <color name="i_am_color_21c">#0000021c</color>
+ <color name="i_am_color_21d">#0000021d</color>
+ <color name="i_am_color_21e">#0000021e</color>
+ <color name="i_am_color_21f">#0000021f</color>
+ <color name="i_am_color_220">#00000220</color>
+ <color name="i_am_color_221">#00000221</color>
+ <color name="i_am_color_222">#00000222</color>
+ <color name="i_am_color_223">#00000223</color>
+ <color name="i_am_color_224">#00000224</color>
+ <color name="i_am_color_225">#00000225</color>
+ <color name="i_am_color_226">#00000226</color>
+ <color name="i_am_color_227">#00000227</color>
+ <color name="i_am_color_228">#00000228</color>
+ <color name="i_am_color_229">#00000229</color>
+ <color name="i_am_color_22a">#0000022a</color>
+ <color name="i_am_color_22b">#0000022b</color>
+ <color name="i_am_color_22c">#0000022c</color>
+ <color name="i_am_color_22d">#0000022d</color>
+ <color name="i_am_color_22e">#0000022e</color>
+ <color name="i_am_color_22f">#0000022f</color>
+ <color name="i_am_color_230">#00000230</color>
+ <color name="i_am_color_231">#00000231</color>
+ <color name="i_am_color_232">#00000232</color>
+ <color name="i_am_color_233">#00000233</color>
+ <color name="i_am_color_234">#00000234</color>
+ <color name="i_am_color_235">#00000235</color>
+ <color name="i_am_color_236">#00000236</color>
+ <color name="i_am_color_237">#00000237</color>
+ <color name="i_am_color_238">#00000238</color>
+ <color name="i_am_color_239">#00000239</color>
+ <color name="i_am_color_23a">#0000023a</color>
+ <color name="i_am_color_23b">#0000023b</color>
+ <color name="i_am_color_23c">#0000023c</color>
+ <color name="i_am_color_23d">#0000023d</color>
+ <color name="i_am_color_23e">#0000023e</color>
+ <color name="i_am_color_23f">#0000023f</color>
+ <color name="i_am_color_240">#00000240</color>
+ <color name="i_am_color_241">#00000241</color>
+ <color name="i_am_color_242">#00000242</color>
+ <color name="i_am_color_243">#00000243</color>
+ <color name="i_am_color_244">#00000244</color>
+ <color name="i_am_color_245">#00000245</color>
+ <color name="i_am_color_246">#00000246</color>
+ <color name="i_am_color_247">#00000247</color>
+ <color name="i_am_color_248">#00000248</color>
+ <color name="i_am_color_249">#00000249</color>
+ <color name="i_am_color_24a">#0000024a</color>
+ <color name="i_am_color_24b">#0000024b</color>
+ <color name="i_am_color_24c">#0000024c</color>
+ <color name="i_am_color_24d">#0000024d</color>
+ <color name="i_am_color_24e">#0000024e</color>
+ <color name="i_am_color_24f">#0000024f</color>
+ <color name="i_am_color_250">#00000250</color>
+ <color name="i_am_color_251">#00000251</color>
+ <color name="i_am_color_252">#00000252</color>
+ <color name="i_am_color_253">#00000253</color>
+ <color name="i_am_color_254">#00000254</color>
+ <color name="i_am_color_255">#00000255</color>
+ <color name="i_am_color_256">#00000256</color>
+ <color name="i_am_color_257">#00000257</color>
+ <color name="i_am_color_258">#00000258</color>
+ <color name="i_am_color_259">#00000259</color>
+ <color name="i_am_color_25a">#0000025a</color>
+ <color name="i_am_color_25b">#0000025b</color>
+ <color name="i_am_color_25c">#0000025c</color>
+ <color name="i_am_color_25d">#0000025d</color>
+ <color name="i_am_color_25e">#0000025e</color>
+ <color name="i_am_color_25f">#0000025f</color>
+ <color name="i_am_color_260">#00000260</color>
+ <color name="i_am_color_261">#00000261</color>
+ <color name="i_am_color_262">#00000262</color>
+ <color name="i_am_color_263">#00000263</color>
+ <color name="i_am_color_264">#00000264</color>
+ <color name="i_am_color_265">#00000265</color>
+ <color name="i_am_color_266">#00000266</color>
+ <color name="i_am_color_267">#00000267</color>
+ <color name="i_am_color_268">#00000268</color>
+ <color name="i_am_color_269">#00000269</color>
+ <color name="i_am_color_26a">#0000026a</color>
+ <color name="i_am_color_26b">#0000026b</color>
+ <color name="i_am_color_26c">#0000026c</color>
+ <color name="i_am_color_26d">#0000026d</color>
+ <color name="i_am_color_26e">#0000026e</color>
+ <color name="i_am_color_26f">#0000026f</color>
+ <color name="i_am_color_270">#00000270</color>
+ <color name="i_am_color_271">#00000271</color>
+ <color name="i_am_color_272">#00000272</color>
+ <color name="i_am_color_273">#00000273</color>
+ <color name="i_am_color_274">#00000274</color>
+ <color name="i_am_color_275">#00000275</color>
+ <color name="i_am_color_276">#00000276</color>
+ <color name="i_am_color_277">#00000277</color>
+ <color name="i_am_color_278">#00000278</color>
+ <color name="i_am_color_279">#00000279</color>
+ <color name="i_am_color_27a">#0000027a</color>
+ <color name="i_am_color_27b">#0000027b</color>
+ <color name="i_am_color_27c">#0000027c</color>
+ <color name="i_am_color_27d">#0000027d</color>
+ <color name="i_am_color_27e">#0000027e</color>
+ <color name="i_am_color_27f">#0000027f</color>
+ <color name="i_am_color_280">#00000280</color>
+ <color name="i_am_color_281">#00000281</color>
+ <color name="i_am_color_282">#00000282</color>
+ <color name="i_am_color_283">#00000283</color>
+ <color name="i_am_color_284">#00000284</color>
+ <color name="i_am_color_285">#00000285</color>
+ <color name="i_am_color_286">#00000286</color>
+ <color name="i_am_color_287">#00000287</color>
+ <color name="i_am_color_288">#00000288</color>
+ <color name="i_am_color_289">#00000289</color>
+ <color name="i_am_color_28a">#0000028a</color>
+ <color name="i_am_color_28b">#0000028b</color>
+ <color name="i_am_color_28c">#0000028c</color>
+ <color name="i_am_color_28d">#0000028d</color>
+ <color name="i_am_color_28e">#0000028e</color>
+ <color name="i_am_color_28f">#0000028f</color>
+ <color name="i_am_color_290">#00000290</color>
+ <color name="i_am_color_291">#00000291</color>
+ <color name="i_am_color_292">#00000292</color>
+ <color name="i_am_color_293">#00000293</color>
+ <color name="i_am_color_294">#00000294</color>
+ <color name="i_am_color_295">#00000295</color>
+ <color name="i_am_color_296">#00000296</color>
+ <color name="i_am_color_297">#00000297</color>
+ <color name="i_am_color_298">#00000298</color>
+ <color name="i_am_color_299">#00000299</color>
+ <color name="i_am_color_29a">#0000029a</color>
+ <color name="i_am_color_29b">#0000029b</color>
+ <color name="i_am_color_29c">#0000029c</color>
+ <color name="i_am_color_29d">#0000029d</color>
+ <color name="i_am_color_29e">#0000029e</color>
+ <color name="i_am_color_29f">#0000029f</color>
+ <color name="i_am_color_2a0">#000002a0</color>
+ <color name="i_am_color_2a1">#000002a1</color>
+ <color name="i_am_color_2a2">#000002a2</color>
+ <color name="i_am_color_2a3">#000002a3</color>
+ <color name="i_am_color_2a4">#000002a4</color>
+ <color name="i_am_color_2a5">#000002a5</color>
+ <color name="i_am_color_2a6">#000002a6</color>
+ <color name="i_am_color_2a7">#000002a7</color>
+ <color name="i_am_color_2a8">#000002a8</color>
+ <color name="i_am_color_2a9">#000002a9</color>
+ <color name="i_am_color_2aa">#000002aa</color>
+ <color name="i_am_color_2ab">#000002ab</color>
+ <color name="i_am_color_2ac">#000002ac</color>
+ <color name="i_am_color_2ad">#000002ad</color>
+ <color name="i_am_color_2ae">#000002ae</color>
+ <color name="i_am_color_2af">#000002af</color>
+ <color name="i_am_color_2b0">#000002b0</color>
+ <color name="i_am_color_2b1">#000002b1</color>
+ <color name="i_am_color_2b2">#000002b2</color>
+ <color name="i_am_color_2b3">#000002b3</color>
+ <color name="i_am_color_2b4">#000002b4</color>
+ <color name="i_am_color_2b5">#000002b5</color>
+ <color name="i_am_color_2b6">#000002b6</color>
+ <color name="i_am_color_2b7">#000002b7</color>
+ <color name="i_am_color_2b8">#000002b8</color>
+ <color name="i_am_color_2b9">#000002b9</color>
+ <color name="i_am_color_2ba">#000002ba</color>
+ <color name="i_am_color_2bb">#000002bb</color>
+ <color name="i_am_color_2bc">#000002bc</color>
+ <color name="i_am_color_2bd">#000002bd</color>
+ <color name="i_am_color_2be">#000002be</color>
+ <color name="i_am_color_2bf">#000002bf</color>
+ <color name="i_am_color_2c0">#000002c0</color>
+ <color name="i_am_color_2c1">#000002c1</color>
+ <color name="i_am_color_2c2">#000002c2</color>
+ <color name="i_am_color_2c3">#000002c3</color>
+ <color name="i_am_color_2c4">#000002c4</color>
+ <color name="i_am_color_2c5">#000002c5</color>
+ <color name="i_am_color_2c6">#000002c6</color>
+ <color name="i_am_color_2c7">#000002c7</color>
+ <color name="i_am_color_2c8">#000002c8</color>
+ <color name="i_am_color_2c9">#000002c9</color>
+ <color name="i_am_color_2ca">#000002ca</color>
+ <color name="i_am_color_2cb">#000002cb</color>
+ <color name="i_am_color_2cc">#000002cc</color>
+ <color name="i_am_color_2cd">#000002cd</color>
+ <color name="i_am_color_2ce">#000002ce</color>
+ <color name="i_am_color_2cf">#000002cf</color>
+ <color name="i_am_color_2d0">#000002d0</color>
+ <color name="i_am_color_2d1">#000002d1</color>
+ <color name="i_am_color_2d2">#000002d2</color>
+ <color name="i_am_color_2d3">#000002d3</color>
+ <color name="i_am_color_2d4">#000002d4</color>
+ <color name="i_am_color_2d5">#000002d5</color>
+ <color name="i_am_color_2d6">#000002d6</color>
+ <color name="i_am_color_2d7">#000002d7</color>
+ <color name="i_am_color_2d8">#000002d8</color>
+ <color name="i_am_color_2d9">#000002d9</color>
+ <color name="i_am_color_2da">#000002da</color>
+ <color name="i_am_color_2db">#000002db</color>
+ <color name="i_am_color_2dc">#000002dc</color>
+ <color name="i_am_color_2dd">#000002dd</color>
+ <color name="i_am_color_2de">#000002de</color>
+ <color name="i_am_color_2df">#000002df</color>
+ <color name="i_am_color_2e0">#000002e0</color>
+ <color name="i_am_color_2e1">#000002e1</color>
+ <color name="i_am_color_2e2">#000002e2</color>
+ <color name="i_am_color_2e3">#000002e3</color>
+ <color name="i_am_color_2e4">#000002e4</color>
+ <color name="i_am_color_2e5">#000002e5</color>
+ <color name="i_am_color_2e6">#000002e6</color>
+ <color name="i_am_color_2e7">#000002e7</color>
+ <color name="i_am_color_2e8">#000002e8</color>
+ <color name="i_am_color_2e9">#000002e9</color>
+ <color name="i_am_color_2ea">#000002ea</color>
+ <color name="i_am_color_2eb">#000002eb</color>
+ <color name="i_am_color_2ec">#000002ec</color>
+ <color name="i_am_color_2ed">#000002ed</color>
+ <color name="i_am_color_2ee">#000002ee</color>
+ <color name="i_am_color_2ef">#000002ef</color>
+ <color name="i_am_color_2f0">#000002f0</color>
+ <color name="i_am_color_2f1">#000002f1</color>
+ <color name="i_am_color_2f2">#000002f2</color>
+ <color name="i_am_color_2f3">#000002f3</color>
+ <color name="i_am_color_2f4">#000002f4</color>
+ <color name="i_am_color_2f5">#000002f5</color>
+ <color name="i_am_color_2f6">#000002f6</color>
+ <color name="i_am_color_2f7">#000002f7</color>
+ <color name="i_am_color_2f8">#000002f8</color>
+ <color name="i_am_color_2f9">#000002f9</color>
+ <color name="i_am_color_2fa">#000002fa</color>
+ <color name="i_am_color_2fb">#000002fb</color>
+ <color name="i_am_color_2fc">#000002fc</color>
+ <color name="i_am_color_2fd">#000002fd</color>
+ <color name="i_am_color_2fe">#000002fe</color>
+ <color name="i_am_color_2ff">#000002ff</color>
+ <color name="i_am_color_300">#00000300</color>
+ <color name="i_am_color_301">#00000301</color>
+ <color name="i_am_color_302">#00000302</color>
+ <color name="i_am_color_303">#00000303</color>
+ <color name="i_am_color_304">#00000304</color>
+ <color name="i_am_color_305">#00000305</color>
+ <color name="i_am_color_306">#00000306</color>
+ <color name="i_am_color_307">#00000307</color>
+ <color name="i_am_color_308">#00000308</color>
+ <color name="i_am_color_309">#00000309</color>
+ <color name="i_am_color_30a">#0000030a</color>
+ <color name="i_am_color_30b">#0000030b</color>
+ <color name="i_am_color_30c">#0000030c</color>
+ <color name="i_am_color_30d">#0000030d</color>
+ <color name="i_am_color_30e">#0000030e</color>
+ <color name="i_am_color_30f">#0000030f</color>
+ <color name="i_am_color_310">#00000310</color>
+ <color name="i_am_color_311">#00000311</color>
+ <color name="i_am_color_312">#00000312</color>
+ <color name="i_am_color_313">#00000313</color>
+ <color name="i_am_color_314">#00000314</color>
+ <color name="i_am_color_315">#00000315</color>
+ <color name="i_am_color_316">#00000316</color>
+ <color name="i_am_color_317">#00000317</color>
+ <color name="i_am_color_318">#00000318</color>
+ <color name="i_am_color_319">#00000319</color>
+ <color name="i_am_color_31a">#0000031a</color>
+ <color name="i_am_color_31b">#0000031b</color>
+ <color name="i_am_color_31c">#0000031c</color>
+ <color name="i_am_color_31d">#0000031d</color>
+ <color name="i_am_color_31e">#0000031e</color>
+ <color name="i_am_color_31f">#0000031f</color>
+ <color name="i_am_color_320">#00000320</color>
+ <color name="i_am_color_321">#00000321</color>
+ <color name="i_am_color_322">#00000322</color>
+ <color name="i_am_color_323">#00000323</color>
+ <color name="i_am_color_324">#00000324</color>
+ <color name="i_am_color_325">#00000325</color>
+ <color name="i_am_color_326">#00000326</color>
+ <color name="i_am_color_327">#00000327</color>
+ <color name="i_am_color_328">#00000328</color>
+ <color name="i_am_color_329">#00000329</color>
+ <color name="i_am_color_32a">#0000032a</color>
+ <color name="i_am_color_32b">#0000032b</color>
+ <color name="i_am_color_32c">#0000032c</color>
+ <color name="i_am_color_32d">#0000032d</color>
+ <color name="i_am_color_32e">#0000032e</color>
+ <color name="i_am_color_32f">#0000032f</color>
+ <color name="i_am_color_330">#00000330</color>
+ <color name="i_am_color_331">#00000331</color>
+ <color name="i_am_color_332">#00000332</color>
+ <color name="i_am_color_333">#00000333</color>
+ <color name="i_am_color_334">#00000334</color>
+ <color name="i_am_color_335">#00000335</color>
+ <color name="i_am_color_336">#00000336</color>
+ <color name="i_am_color_337">#00000337</color>
+ <color name="i_am_color_338">#00000338</color>
+ <color name="i_am_color_339">#00000339</color>
+ <color name="i_am_color_33a">#0000033a</color>
+ <color name="i_am_color_33b">#0000033b</color>
+ <color name="i_am_color_33c">#0000033c</color>
+ <color name="i_am_color_33d">#0000033d</color>
+ <color name="i_am_color_33e">#0000033e</color>
+ <color name="i_am_color_33f">#0000033f</color>
+ <color name="i_am_color_340">#00000340</color>
+ <color name="i_am_color_341">#00000341</color>
+ <color name="i_am_color_342">#00000342</color>
+ <color name="i_am_color_343">#00000343</color>
+ <color name="i_am_color_344">#00000344</color>
+ <color name="i_am_color_345">#00000345</color>
+ <color name="i_am_color_346">#00000346</color>
+ <color name="i_am_color_347">#00000347</color>
+ <color name="i_am_color_348">#00000348</color>
+ <color name="i_am_color_349">#00000349</color>
+ <color name="i_am_color_34a">#0000034a</color>
+ <color name="i_am_color_34b">#0000034b</color>
+ <color name="i_am_color_34c">#0000034c</color>
+ <color name="i_am_color_34d">#0000034d</color>
+ <color name="i_am_color_34e">#0000034e</color>
+ <color name="i_am_color_34f">#0000034f</color>
+ <color name="i_am_color_350">#00000350</color>
+ <color name="i_am_color_351">#00000351</color>
+ <color name="i_am_color_352">#00000352</color>
+ <color name="i_am_color_353">#00000353</color>
+ <color name="i_am_color_354">#00000354</color>
+ <color name="i_am_color_355">#00000355</color>
+ <color name="i_am_color_356">#00000356</color>
+ <color name="i_am_color_357">#00000357</color>
+ <color name="i_am_color_358">#00000358</color>
+ <color name="i_am_color_359">#00000359</color>
+ <color name="i_am_color_35a">#0000035a</color>
+ <color name="i_am_color_35b">#0000035b</color>
+ <color name="i_am_color_35c">#0000035c</color>
+ <color name="i_am_color_35d">#0000035d</color>
+ <color name="i_am_color_35e">#0000035e</color>
+ <color name="i_am_color_35f">#0000035f</color>
+ <color name="i_am_color_360">#00000360</color>
+ <color name="i_am_color_361">#00000361</color>
+ <color name="i_am_color_362">#00000362</color>
+ <color name="i_am_color_363">#00000363</color>
+ <color name="i_am_color_364">#00000364</color>
+ <color name="i_am_color_365">#00000365</color>
+ <color name="i_am_color_366">#00000366</color>
+ <color name="i_am_color_367">#00000367</color>
+ <color name="i_am_color_368">#00000368</color>
+ <color name="i_am_color_369">#00000369</color>
+ <color name="i_am_color_36a">#0000036a</color>
+ <color name="i_am_color_36b">#0000036b</color>
+ <color name="i_am_color_36c">#0000036c</color>
+ <color name="i_am_color_36d">#0000036d</color>
+ <color name="i_am_color_36e">#0000036e</color>
+ <color name="i_am_color_36f">#0000036f</color>
+ <color name="i_am_color_370">#00000370</color>
+ <color name="i_am_color_371">#00000371</color>
+ <color name="i_am_color_372">#00000372</color>
+ <color name="i_am_color_373">#00000373</color>
+ <color name="i_am_color_374">#00000374</color>
+ <color name="i_am_color_375">#00000375</color>
+ <color name="i_am_color_376">#00000376</color>
+ <color name="i_am_color_377">#00000377</color>
+ <color name="i_am_color_378">#00000378</color>
+ <color name="i_am_color_379">#00000379</color>
+ <color name="i_am_color_37a">#0000037a</color>
+ <color name="i_am_color_37b">#0000037b</color>
+ <color name="i_am_color_37c">#0000037c</color>
+ <color name="i_am_color_37d">#0000037d</color>
+ <color name="i_am_color_37e">#0000037e</color>
+ <color name="i_am_color_37f">#0000037f</color>
+ <color name="i_am_color_380">#00000380</color>
+ <color name="i_am_color_381">#00000381</color>
+ <color name="i_am_color_382">#00000382</color>
+ <color name="i_am_color_383">#00000383</color>
+ <color name="i_am_color_384">#00000384</color>
+ <color name="i_am_color_385">#00000385</color>
+ <color name="i_am_color_386">#00000386</color>
+ <color name="i_am_color_387">#00000387</color>
+ <color name="i_am_color_388">#00000388</color>
+ <color name="i_am_color_389">#00000389</color>
+ <color name="i_am_color_38a">#0000038a</color>
+ <color name="i_am_color_38b">#0000038b</color>
+ <color name="i_am_color_38c">#0000038c</color>
+ <color name="i_am_color_38d">#0000038d</color>
+ <color name="i_am_color_38e">#0000038e</color>
+ <color name="i_am_color_38f">#0000038f</color>
+ <color name="i_am_color_390">#00000390</color>
+ <color name="i_am_color_391">#00000391</color>
+ <color name="i_am_color_392">#00000392</color>
+ <color name="i_am_color_393">#00000393</color>
+ <color name="i_am_color_394">#00000394</color>
+ <color name="i_am_color_395">#00000395</color>
+ <color name="i_am_color_396">#00000396</color>
+ <color name="i_am_color_397">#00000397</color>
+ <color name="i_am_color_398">#00000398</color>
+ <color name="i_am_color_399">#00000399</color>
+ <color name="i_am_color_39a">#0000039a</color>
+ <color name="i_am_color_39b">#0000039b</color>
+ <color name="i_am_color_39c">#0000039c</color>
+ <color name="i_am_color_39d">#0000039d</color>
+ <color name="i_am_color_39e">#0000039e</color>
+ <color name="i_am_color_39f">#0000039f</color>
+ <color name="i_am_color_3a0">#000003a0</color>
+ <color name="i_am_color_3a1">#000003a1</color>
+ <color name="i_am_color_3a2">#000003a2</color>
+ <color name="i_am_color_3a3">#000003a3</color>
+ <color name="i_am_color_3a4">#000003a4</color>
+ <color name="i_am_color_3a5">#000003a5</color>
+ <color name="i_am_color_3a6">#000003a6</color>
+ <color name="i_am_color_3a7">#000003a7</color>
+ <color name="i_am_color_3a8">#000003a8</color>
+ <color name="i_am_color_3a9">#000003a9</color>
+ <color name="i_am_color_3aa">#000003aa</color>
+ <color name="i_am_color_3ab">#000003ab</color>
+ <color name="i_am_color_3ac">#000003ac</color>
+ <color name="i_am_color_3ad">#000003ad</color>
+ <color name="i_am_color_3ae">#000003ae</color>
+ <color name="i_am_color_3af">#000003af</color>
+ <color name="i_am_color_3b0">#000003b0</color>
+ <color name="i_am_color_3b1">#000003b1</color>
+ <color name="i_am_color_3b2">#000003b2</color>
+ <color name="i_am_color_3b3">#000003b3</color>
+ <color name="i_am_color_3b4">#000003b4</color>
+ <color name="i_am_color_3b5">#000003b5</color>
+ <color name="i_am_color_3b6">#000003b6</color>
+ <color name="i_am_color_3b7">#000003b7</color>
+ <color name="i_am_color_3b8">#000003b8</color>
+ <color name="i_am_color_3b9">#000003b9</color>
+ <color name="i_am_color_3ba">#000003ba</color>
+ <color name="i_am_color_3bb">#000003bb</color>
+ <color name="i_am_color_3bc">#000003bc</color>
+ <color name="i_am_color_3bd">#000003bd</color>
+ <color name="i_am_color_3be">#000003be</color>
+ <color name="i_am_color_3bf">#000003bf</color>
+ <color name="i_am_color_3c0">#000003c0</color>
+ <color name="i_am_color_3c1">#000003c1</color>
+ <color name="i_am_color_3c2">#000003c2</color>
+ <color name="i_am_color_3c3">#000003c3</color>
+ <color name="i_am_color_3c4">#000003c4</color>
+ <color name="i_am_color_3c5">#000003c5</color>
+ <color name="i_am_color_3c6">#000003c6</color>
+ <color name="i_am_color_3c7">#000003c7</color>
+ <color name="i_am_color_3c8">#000003c8</color>
+ <color name="i_am_color_3c9">#000003c9</color>
+ <color name="i_am_color_3ca">#000003ca</color>
+ <color name="i_am_color_3cb">#000003cb</color>
+ <color name="i_am_color_3cc">#000003cc</color>
+ <color name="i_am_color_3cd">#000003cd</color>
+ <color name="i_am_color_3ce">#000003ce</color>
+ <color name="i_am_color_3cf">#000003cf</color>
+ <color name="i_am_color_3d0">#000003d0</color>
+ <color name="i_am_color_3d1">#000003d1</color>
+ <color name="i_am_color_3d2">#000003d2</color>
+ <color name="i_am_color_3d3">#000003d3</color>
+ <color name="i_am_color_3d4">#000003d4</color>
+ <color name="i_am_color_3d5">#000003d5</color>
+ <color name="i_am_color_3d6">#000003d6</color>
+ <color name="i_am_color_3d7">#000003d7</color>
+ <color name="i_am_color_3d8">#000003d8</color>
+ <color name="i_am_color_3d9">#000003d9</color>
+ <color name="i_am_color_3da">#000003da</color>
+ <color name="i_am_color_3db">#000003db</color>
+ <color name="i_am_color_3dc">#000003dc</color>
+ <color name="i_am_color_3dd">#000003dd</color>
+ <color name="i_am_color_3de">#000003de</color>
+ <color name="i_am_color_3df">#000003df</color>
+ <color name="i_am_color_3e0">#000003e0</color>
+ <color name="i_am_color_3e1">#000003e1</color>
+ <color name="i_am_color_3e2">#000003e2</color>
+ <color name="i_am_color_3e3">#000003e3</color>
+ <color name="i_am_color_3e4">#000003e4</color>
+ <color name="i_am_color_3e5">#000003e5</color>
+ <color name="i_am_color_3e6">#000003e6</color>
+ <color name="i_am_color_3e7">#000003e7</color>
+ <color name="i_am_color_3e8">#000003e8</color>
+ <color name="i_am_color_3e9">#000003e9</color>
+ <color name="i_am_color_3ea">#000003ea</color>
+ <color name="i_am_color_3eb">#000003eb</color>
+ <color name="i_am_color_3ec">#000003ec</color>
+ <color name="i_am_color_3ed">#000003ed</color>
+ <color name="i_am_color_3ee">#000003ee</color>
+ <color name="i_am_color_3ef">#000003ef</color>
+ <color name="i_am_color_3f0">#000003f0</color>
+ <color name="i_am_color_3f1">#000003f1</color>
+ <color name="i_am_color_3f2">#000003f2</color>
+ <color name="i_am_color_3f3">#000003f3</color>
+ <color name="i_am_color_3f4">#000003f4</color>
+ <color name="i_am_color_3f5">#000003f5</color>
+ <color name="i_am_color_3f6">#000003f6</color>
+ <color name="i_am_color_3f7">#000003f7</color>
+ <color name="i_am_color_3f8">#000003f8</color>
+ <color name="i_am_color_3f9">#000003f9</color>
+ <color name="i_am_color_3fa">#000003fa</color>
+ <color name="i_am_color_3fb">#000003fb</color>
+ <color name="i_am_color_3fc">#000003fc</color>
+ <color name="i_am_color_3fd">#000003fd</color>
+ <color name="i_am_color_3fe">#000003fe</color>
+ <color name="i_am_color_3ff">#000003ff</color>
+ <color name="i_am_color_400">#00000400</color>
+ <color name="i_am_color_401">#00000401</color>
+ <color name="i_am_color_402">#00000402</color>
+ <color name="i_am_color_403">#00000403</color>
+ <color name="i_am_color_404">#00000404</color>
+ <color name="i_am_color_405">#00000405</color>
+ <color name="i_am_color_406">#00000406</color>
+ <color name="i_am_color_407">#00000407</color>
+ <color name="i_am_color_408">#00000408</color>
+ <color name="i_am_color_409">#00000409</color>
+ <color name="i_am_color_40a">#0000040a</color>
+ <color name="i_am_color_40b">#0000040b</color>
+ <color name="i_am_color_40c">#0000040c</color>
+ <color name="i_am_color_40d">#0000040d</color>
+ <color name="i_am_color_40e">#0000040e</color>
+ <color name="i_am_color_40f">#0000040f</color>
+ <color name="i_am_color_410">#00000410</color>
+ <color name="i_am_color_411">#00000411</color>
+ <color name="i_am_color_412">#00000412</color>
+ <color name="i_am_color_413">#00000413</color>
+ <color name="i_am_color_414">#00000414</color>
+ <color name="i_am_color_415">#00000415</color>
+ <color name="i_am_color_416">#00000416</color>
+ <color name="i_am_color_417">#00000417</color>
+ <color name="i_am_color_418">#00000418</color>
+ <color name="i_am_color_419">#00000419</color>
+ <color name="i_am_color_41a">#0000041a</color>
+ <color name="i_am_color_41b">#0000041b</color>
+ <color name="i_am_color_41c">#0000041c</color>
+ <color name="i_am_color_41d">#0000041d</color>
+ <color name="i_am_color_41e">#0000041e</color>
+ <color name="i_am_color_41f">#0000041f</color>
+ <color name="i_am_color_420">#00000420</color>
+ <color name="i_am_color_421">#00000421</color>
+ <color name="i_am_color_422">#00000422</color>
+ <color name="i_am_color_423">#00000423</color>
+ <color name="i_am_color_424">#00000424</color>
+ <color name="i_am_color_425">#00000425</color>
+ <color name="i_am_color_426">#00000426</color>
+ <color name="i_am_color_427">#00000427</color>
+ <color name="i_am_color_428">#00000428</color>
+ <color name="i_am_color_429">#00000429</color>
+ <color name="i_am_color_42a">#0000042a</color>
+ <color name="i_am_color_42b">#0000042b</color>
+ <color name="i_am_color_42c">#0000042c</color>
+ <color name="i_am_color_42d">#0000042d</color>
+ <color name="i_am_color_42e">#0000042e</color>
+ <color name="i_am_color_42f">#0000042f</color>
+ <color name="i_am_color_430">#00000430</color>
+ <color name="i_am_color_431">#00000431</color>
+ <color name="i_am_color_432">#00000432</color>
+ <color name="i_am_color_433">#00000433</color>
+ <color name="i_am_color_434">#00000434</color>
+ <color name="i_am_color_435">#00000435</color>
+ <color name="i_am_color_436">#00000436</color>
+ <color name="i_am_color_437">#00000437</color>
+ <color name="i_am_color_438">#00000438</color>
+ <color name="i_am_color_439">#00000439</color>
+ <color name="i_am_color_43a">#0000043a</color>
+ <color name="i_am_color_43b">#0000043b</color>
+ <color name="i_am_color_43c">#0000043c</color>
+ <color name="i_am_color_43d">#0000043d</color>
+ <color name="i_am_color_43e">#0000043e</color>
+ <color name="i_am_color_43f">#0000043f</color>
+ <color name="i_am_color_440">#00000440</color>
+ <color name="i_am_color_441">#00000441</color>
+ <color name="i_am_color_442">#00000442</color>
+ <color name="i_am_color_443">#00000443</color>
+ <color name="i_am_color_444">#00000444</color>
+ <color name="i_am_color_445">#00000445</color>
+ <color name="i_am_color_446">#00000446</color>
+ <color name="i_am_color_447">#00000447</color>
+ <color name="i_am_color_448">#00000448</color>
+ <color name="i_am_color_449">#00000449</color>
+ <color name="i_am_color_44a">#0000044a</color>
+ <color name="i_am_color_44b">#0000044b</color>
+ <color name="i_am_color_44c">#0000044c</color>
+ <color name="i_am_color_44d">#0000044d</color>
+ <color name="i_am_color_44e">#0000044e</color>
+ <color name="i_am_color_44f">#0000044f</color>
+ <color name="i_am_color_450">#00000450</color>
+ <color name="i_am_color_451">#00000451</color>
+ <color name="i_am_color_452">#00000452</color>
+ <color name="i_am_color_453">#00000453</color>
+ <color name="i_am_color_454">#00000454</color>
+ <color name="i_am_color_455">#00000455</color>
+ <color name="i_am_color_456">#00000456</color>
+ <color name="i_am_color_457">#00000457</color>
+ <color name="i_am_color_458">#00000458</color>
+ <color name="i_am_color_459">#00000459</color>
+ <color name="i_am_color_45a">#0000045a</color>
+ <color name="i_am_color_45b">#0000045b</color>
+ <color name="i_am_color_45c">#0000045c</color>
+ <color name="i_am_color_45d">#0000045d</color>
+ <color name="i_am_color_45e">#0000045e</color>
+ <color name="i_am_color_45f">#0000045f</color>
+ <color name="i_am_color_460">#00000460</color>
+ <color name="i_am_color_461">#00000461</color>
+ <color name="i_am_color_462">#00000462</color>
+ <color name="i_am_color_463">#00000463</color>
+ <color name="i_am_color_464">#00000464</color>
+ <color name="i_am_color_465">#00000465</color>
+ <color name="i_am_color_466">#00000466</color>
+ <color name="i_am_color_467">#00000467</color>
+ <color name="i_am_color_468">#00000468</color>
+ <color name="i_am_color_469">#00000469</color>
+ <color name="i_am_color_46a">#0000046a</color>
+ <color name="i_am_color_46b">#0000046b</color>
+ <color name="i_am_color_46c">#0000046c</color>
+ <color name="i_am_color_46d">#0000046d</color>
+ <color name="i_am_color_46e">#0000046e</color>
+ <color name="i_am_color_46f">#0000046f</color>
+ <color name="i_am_color_470">#00000470</color>
+ <color name="i_am_color_471">#00000471</color>
+ <color name="i_am_color_472">#00000472</color>
+ <color name="i_am_color_473">#00000473</color>
+ <color name="i_am_color_474">#00000474</color>
+ <color name="i_am_color_475">#00000475</color>
+ <color name="i_am_color_476">#00000476</color>
+ <color name="i_am_color_477">#00000477</color>
+ <color name="i_am_color_478">#00000478</color>
+ <color name="i_am_color_479">#00000479</color>
+ <color name="i_am_color_47a">#0000047a</color>
+ <color name="i_am_color_47b">#0000047b</color>
+ <color name="i_am_color_47c">#0000047c</color>
+ <color name="i_am_color_47d">#0000047d</color>
+ <color name="i_am_color_47e">#0000047e</color>
+ <color name="i_am_color_47f">#0000047f</color>
+ <color name="i_am_color_480">#00000480</color>
+ <color name="i_am_color_481">#00000481</color>
+ <color name="i_am_color_482">#00000482</color>
+ <color name="i_am_color_483">#00000483</color>
+ <color name="i_am_color_484">#00000484</color>
+ <color name="i_am_color_485">#00000485</color>
+ <color name="i_am_color_486">#00000486</color>
+ <color name="i_am_color_487">#00000487</color>
+ <color name="i_am_color_488">#00000488</color>
+ <color name="i_am_color_489">#00000489</color>
+ <color name="i_am_color_48a">#0000048a</color>
+ <color name="i_am_color_48b">#0000048b</color>
+ <color name="i_am_color_48c">#0000048c</color>
+ <color name="i_am_color_48d">#0000048d</color>
+ <color name="i_am_color_48e">#0000048e</color>
+ <color name="i_am_color_48f">#0000048f</color>
+ <color name="i_am_color_490">#00000490</color>
+ <color name="i_am_color_491">#00000491</color>
+ <color name="i_am_color_492">#00000492</color>
+ <color name="i_am_color_493">#00000493</color>
+ <color name="i_am_color_494">#00000494</color>
+ <color name="i_am_color_495">#00000495</color>
+ <color name="i_am_color_496">#00000496</color>
+ <color name="i_am_color_497">#00000497</color>
+ <color name="i_am_color_498">#00000498</color>
+ <color name="i_am_color_499">#00000499</color>
+ <color name="i_am_color_49a">#0000049a</color>
+ <color name="i_am_color_49b">#0000049b</color>
+ <color name="i_am_color_49c">#0000049c</color>
+ <color name="i_am_color_49d">#0000049d</color>
+ <color name="i_am_color_49e">#0000049e</color>
+ <color name="i_am_color_49f">#0000049f</color>
+ <color name="i_am_color_4a0">#000004a0</color>
+ <color name="i_am_color_4a1">#000004a1</color>
+ <color name="i_am_color_4a2">#000004a2</color>
+ <color name="i_am_color_4a3">#000004a3</color>
+ <color name="i_am_color_4a4">#000004a4</color>
+ <color name="i_am_color_4a5">#000004a5</color>
+ <color name="i_am_color_4a6">#000004a6</color>
+ <color name="i_am_color_4a7">#000004a7</color>
+ <color name="i_am_color_4a8">#000004a8</color>
+ <color name="i_am_color_4a9">#000004a9</color>
+ <color name="i_am_color_4aa">#000004aa</color>
+ <color name="i_am_color_4ab">#000004ab</color>
+ <color name="i_am_color_4ac">#000004ac</color>
+ <color name="i_am_color_4ad">#000004ad</color>
+ <color name="i_am_color_4ae">#000004ae</color>
+ <color name="i_am_color_4af">#000004af</color>
+ <color name="i_am_color_4b0">#000004b0</color>
+ <color name="i_am_color_4b1">#000004b1</color>
+ <color name="i_am_color_4b2">#000004b2</color>
+ <color name="i_am_color_4b3">#000004b3</color>
+ <color name="i_am_color_4b4">#000004b4</color>
+ <color name="i_am_color_4b5">#000004b5</color>
+ <color name="i_am_color_4b6">#000004b6</color>
+ <color name="i_am_color_4b7">#000004b7</color>
+ <color name="i_am_color_4b8">#000004b8</color>
+ <color name="i_am_color_4b9">#000004b9</color>
+ <color name="i_am_color_4ba">#000004ba</color>
+ <color name="i_am_color_4bb">#000004bb</color>
+ <color name="i_am_color_4bc">#000004bc</color>
+ <color name="i_am_color_4bd">#000004bd</color>
+ <color name="i_am_color_4be">#000004be</color>
+ <color name="i_am_color_4bf">#000004bf</color>
+ <color name="i_am_color_4c0">#000004c0</color>
+ <color name="i_am_color_4c1">#000004c1</color>
+ <color name="i_am_color_4c2">#000004c2</color>
+ <color name="i_am_color_4c3">#000004c3</color>
+ <color name="i_am_color_4c4">#000004c4</color>
+ <color name="i_am_color_4c5">#000004c5</color>
+ <color name="i_am_color_4c6">#000004c6</color>
+ <color name="i_am_color_4c7">#000004c7</color>
+ <color name="i_am_color_4c8">#000004c8</color>
+ <color name="i_am_color_4c9">#000004c9</color>
+ <color name="i_am_color_4ca">#000004ca</color>
+ <color name="i_am_color_4cb">#000004cb</color>
+ <color name="i_am_color_4cc">#000004cc</color>
+ <color name="i_am_color_4cd">#000004cd</color>
+ <color name="i_am_color_4ce">#000004ce</color>
+ <color name="i_am_color_4cf">#000004cf</color>
+ <color name="i_am_color_4d0">#000004d0</color>
+ <color name="i_am_color_4d1">#000004d1</color>
+ <color name="i_am_color_4d2">#000004d2</color>
+ <color name="i_am_color_4d3">#000004d3</color>
+ <color name="i_am_color_4d4">#000004d4</color>
+ <color name="i_am_color_4d5">#000004d5</color>
+ <color name="i_am_color_4d6">#000004d6</color>
+ <color name="i_am_color_4d7">#000004d7</color>
+ <color name="i_am_color_4d8">#000004d8</color>
+ <color name="i_am_color_4d9">#000004d9</color>
+ <color name="i_am_color_4da">#000004da</color>
+ <color name="i_am_color_4db">#000004db</color>
+ <color name="i_am_color_4dc">#000004dc</color>
+ <color name="i_am_color_4dd">#000004dd</color>
+ <color name="i_am_color_4de">#000004de</color>
+ <color name="i_am_color_4df">#000004df</color>
+ <color name="i_am_color_4e0">#000004e0</color>
+ <color name="i_am_color_4e1">#000004e1</color>
+ <color name="i_am_color_4e2">#000004e2</color>
+ <color name="i_am_color_4e3">#000004e3</color>
+ <color name="i_am_color_4e4">#000004e4</color>
+ <color name="i_am_color_4e5">#000004e5</color>
+ <color name="i_am_color_4e6">#000004e6</color>
+ <color name="i_am_color_4e7">#000004e7</color>
+ <color name="i_am_color_4e8">#000004e8</color>
+ <color name="i_am_color_4e9">#000004e9</color>
+ <color name="i_am_color_4ea">#000004ea</color>
+ <color name="i_am_color_4eb">#000004eb</color>
+ <color name="i_am_color_4ec">#000004ec</color>
+ <color name="i_am_color_4ed">#000004ed</color>
+ <color name="i_am_color_4ee">#000004ee</color>
+ <color name="i_am_color_4ef">#000004ef</color>
+ <color name="i_am_color_4f0">#000004f0</color>
+ <color name="i_am_color_4f1">#000004f1</color>
+ <color name="i_am_color_4f2">#000004f2</color>
+ <color name="i_am_color_4f3">#000004f3</color>
+ <color name="i_am_color_4f4">#000004f4</color>
+ <color name="i_am_color_4f5">#000004f5</color>
+ <color name="i_am_color_4f6">#000004f6</color>
+ <color name="i_am_color_4f7">#000004f7</color>
+ <color name="i_am_color_4f8">#000004f8</color>
+ <color name="i_am_color_4f9">#000004f9</color>
+ <color name="i_am_color_4fa">#000004fa</color>
+ <color name="i_am_color_4fb">#000004fb</color>
+ <color name="i_am_color_4fc">#000004fc</color>
+ <color name="i_am_color_4fd">#000004fd</color>
+ <color name="i_am_color_4fe">#000004fe</color>
+ <color name="i_am_color_4ff">#000004ff</color>
+ <color name="i_am_color_500">#00000500</color>
+ <color name="i_am_color_501">#00000501</color>
+ <color name="i_am_color_502">#00000502</color>
+ <color name="i_am_color_503">#00000503</color>
+ <color name="i_am_color_504">#00000504</color>
+ <color name="i_am_color_505">#00000505</color>
+ <color name="i_am_color_506">#00000506</color>
+ <color name="i_am_color_507">#00000507</color>
+ <color name="i_am_color_508">#00000508</color>
+ <color name="i_am_color_509">#00000509</color>
+ <color name="i_am_color_50a">#0000050a</color>
+ <color name="i_am_color_50b">#0000050b</color>
+ <color name="i_am_color_50c">#0000050c</color>
+ <color name="i_am_color_50d">#0000050d</color>
+ <color name="i_am_color_50e">#0000050e</color>
+ <color name="i_am_color_50f">#0000050f</color>
+ <color name="i_am_color_510">#00000510</color>
+ <color name="i_am_color_511">#00000511</color>
+ <color name="i_am_color_512">#00000512</color>
+ <color name="i_am_color_513">#00000513</color>
+ <color name="i_am_color_514">#00000514</color>
+ <color name="i_am_color_515">#00000515</color>
+ <color name="i_am_color_516">#00000516</color>
+ <color name="i_am_color_517">#00000517</color>
+ <color name="i_am_color_518">#00000518</color>
+ <color name="i_am_color_519">#00000519</color>
+ <color name="i_am_color_51a">#0000051a</color>
+ <color name="i_am_color_51b">#0000051b</color>
+ <color name="i_am_color_51c">#0000051c</color>
+ <color name="i_am_color_51d">#0000051d</color>
+ <color name="i_am_color_51e">#0000051e</color>
+ <color name="i_am_color_51f">#0000051f</color>
+ <color name="i_am_color_520">#00000520</color>
+ <color name="i_am_color_521">#00000521</color>
+ <color name="i_am_color_522">#00000522</color>
+ <color name="i_am_color_523">#00000523</color>
+ <color name="i_am_color_524">#00000524</color>
+ <color name="i_am_color_525">#00000525</color>
+ <color name="i_am_color_526">#00000526</color>
+ <color name="i_am_color_527">#00000527</color>
+ <color name="i_am_color_528">#00000528</color>
+ <color name="i_am_color_529">#00000529</color>
+ <color name="i_am_color_52a">#0000052a</color>
+ <color name="i_am_color_52b">#0000052b</color>
+ <color name="i_am_color_52c">#0000052c</color>
+ <color name="i_am_color_52d">#0000052d</color>
+ <color name="i_am_color_52e">#0000052e</color>
+ <color name="i_am_color_52f">#0000052f</color>
+ <color name="i_am_color_530">#00000530</color>
+ <color name="i_am_color_531">#00000531</color>
+ <color name="i_am_color_532">#00000532</color>
+ <color name="i_am_color_533">#00000533</color>
+ <color name="i_am_color_534">#00000534</color>
+ <color name="i_am_color_535">#00000535</color>
+ <color name="i_am_color_536">#00000536</color>
+ <color name="i_am_color_537">#00000537</color>
+ <color name="i_am_color_538">#00000538</color>
+ <color name="i_am_color_539">#00000539</color>
+ <color name="i_am_color_53a">#0000053a</color>
+ <color name="i_am_color_53b">#0000053b</color>
+ <color name="i_am_color_53c">#0000053c</color>
+ <color name="i_am_color_53d">#0000053d</color>
+ <color name="i_am_color_53e">#0000053e</color>
+ <color name="i_am_color_53f">#0000053f</color>
+ <color name="i_am_color_540">#00000540</color>
+ <color name="i_am_color_541">#00000541</color>
+ <color name="i_am_color_542">#00000542</color>
+ <color name="i_am_color_543">#00000543</color>
+ <color name="i_am_color_544">#00000544</color>
+ <color name="i_am_color_545">#00000545</color>
+ <color name="i_am_color_546">#00000546</color>
+ <color name="i_am_color_547">#00000547</color>
+ <color name="i_am_color_548">#00000548</color>
+ <color name="i_am_color_549">#00000549</color>
+ <color name="i_am_color_54a">#0000054a</color>
+ <color name="i_am_color_54b">#0000054b</color>
+ <color name="i_am_color_54c">#0000054c</color>
+ <color name="i_am_color_54d">#0000054d</color>
+ <color name="i_am_color_54e">#0000054e</color>
+ <color name="i_am_color_54f">#0000054f</color>
+ <color name="i_am_color_550">#00000550</color>
+ <color name="i_am_color_551">#00000551</color>
+ <color name="i_am_color_552">#00000552</color>
+ <color name="i_am_color_553">#00000553</color>
+ <color name="i_am_color_554">#00000554</color>
+ <color name="i_am_color_555">#00000555</color>
+ <color name="i_am_color_556">#00000556</color>
+ <color name="i_am_color_557">#00000557</color>
+ <color name="i_am_color_558">#00000558</color>
+ <color name="i_am_color_559">#00000559</color>
+ <color name="i_am_color_55a">#0000055a</color>
+ <color name="i_am_color_55b">#0000055b</color>
+ <color name="i_am_color_55c">#0000055c</color>
+ <color name="i_am_color_55d">#0000055d</color>
+ <color name="i_am_color_55e">#0000055e</color>
+ <color name="i_am_color_55f">#0000055f</color>
+ <color name="i_am_color_560">#00000560</color>
+ <color name="i_am_color_561">#00000561</color>
+ <color name="i_am_color_562">#00000562</color>
+ <color name="i_am_color_563">#00000563</color>
+ <color name="i_am_color_564">#00000564</color>
+ <color name="i_am_color_565">#00000565</color>
+ <color name="i_am_color_566">#00000566</color>
+ <color name="i_am_color_567">#00000567</color>
+ <color name="i_am_color_568">#00000568</color>
+ <color name="i_am_color_569">#00000569</color>
+ <color name="i_am_color_56a">#0000056a</color>
+ <color name="i_am_color_56b">#0000056b</color>
+ <color name="i_am_color_56c">#0000056c</color>
+ <color name="i_am_color_56d">#0000056d</color>
+ <color name="i_am_color_56e">#0000056e</color>
+ <color name="i_am_color_56f">#0000056f</color>
+ <color name="i_am_color_570">#00000570</color>
+ <color name="i_am_color_571">#00000571</color>
+ <color name="i_am_color_572">#00000572</color>
+ <color name="i_am_color_573">#00000573</color>
+ <color name="i_am_color_574">#00000574</color>
+ <color name="i_am_color_575">#00000575</color>
+ <color name="i_am_color_576">#00000576</color>
+ <color name="i_am_color_577">#00000577</color>
+ <color name="i_am_color_578">#00000578</color>
+ <color name="i_am_color_579">#00000579</color>
+ <color name="i_am_color_57a">#0000057a</color>
+ <color name="i_am_color_57b">#0000057b</color>
+ <color name="i_am_color_57c">#0000057c</color>
+ <color name="i_am_color_57d">#0000057d</color>
+ <color name="i_am_color_57e">#0000057e</color>
+ <color name="i_am_color_57f">#0000057f</color>
+ <color name="i_am_color_580">#00000580</color>
+ <color name="i_am_color_581">#00000581</color>
+ <color name="i_am_color_582">#00000582</color>
+ <color name="i_am_color_583">#00000583</color>
+ <color name="i_am_color_584">#00000584</color>
+ <color name="i_am_color_585">#00000585</color>
+ <color name="i_am_color_586">#00000586</color>
+ <color name="i_am_color_587">#00000587</color>
+ <color name="i_am_color_588">#00000588</color>
+ <color name="i_am_color_589">#00000589</color>
+ <color name="i_am_color_58a">#0000058a</color>
+ <color name="i_am_color_58b">#0000058b</color>
+ <color name="i_am_color_58c">#0000058c</color>
+ <color name="i_am_color_58d">#0000058d</color>
+ <color name="i_am_color_58e">#0000058e</color>
+ <color name="i_am_color_58f">#0000058f</color>
+ <color name="i_am_color_590">#00000590</color>
+ <color name="i_am_color_591">#00000591</color>
+ <color name="i_am_color_592">#00000592</color>
+ <color name="i_am_color_593">#00000593</color>
+ <color name="i_am_color_594">#00000594</color>
+ <color name="i_am_color_595">#00000595</color>
+ <color name="i_am_color_596">#00000596</color>
+ <color name="i_am_color_597">#00000597</color>
+ <color name="i_am_color_598">#00000598</color>
+ <color name="i_am_color_599">#00000599</color>
+ <color name="i_am_color_59a">#0000059a</color>
+ <color name="i_am_color_59b">#0000059b</color>
+ <color name="i_am_color_59c">#0000059c</color>
+ <color name="i_am_color_59d">#0000059d</color>
+ <color name="i_am_color_59e">#0000059e</color>
+ <color name="i_am_color_59f">#0000059f</color>
+ <color name="i_am_color_5a0">#000005a0</color>
+ <color name="i_am_color_5a1">#000005a1</color>
+ <color name="i_am_color_5a2">#000005a2</color>
+ <color name="i_am_color_5a3">#000005a3</color>
+ <color name="i_am_color_5a4">#000005a4</color>
+ <color name="i_am_color_5a5">#000005a5</color>
+ <color name="i_am_color_5a6">#000005a6</color>
+ <color name="i_am_color_5a7">#000005a7</color>
+ <color name="i_am_color_5a8">#000005a8</color>
+ <color name="i_am_color_5a9">#000005a9</color>
+ <color name="i_am_color_5aa">#000005aa</color>
+ <color name="i_am_color_5ab">#000005ab</color>
+ <color name="i_am_color_5ac">#000005ac</color>
+ <color name="i_am_color_5ad">#000005ad</color>
+ <color name="i_am_color_5ae">#000005ae</color>
+ <color name="i_am_color_5af">#000005af</color>
+ <color name="i_am_color_5b0">#000005b0</color>
+ <color name="i_am_color_5b1">#000005b1</color>
+ <color name="i_am_color_5b2">#000005b2</color>
+ <color name="i_am_color_5b3">#000005b3</color>
+ <color name="i_am_color_5b4">#000005b4</color>
+ <color name="i_am_color_5b5">#000005b5</color>
+ <color name="i_am_color_5b6">#000005b6</color>
+ <color name="i_am_color_5b7">#000005b7</color>
+ <color name="i_am_color_5b8">#000005b8</color>
+ <color name="i_am_color_5b9">#000005b9</color>
+ <color name="i_am_color_5ba">#000005ba</color>
+ <color name="i_am_color_5bb">#000005bb</color>
+ <color name="i_am_color_5bc">#000005bc</color>
+ <color name="i_am_color_5bd">#000005bd</color>
+ <color name="i_am_color_5be">#000005be</color>
+ <color name="i_am_color_5bf">#000005bf</color>
+ <color name="i_am_color_5c0">#000005c0</color>
+ <color name="i_am_color_5c1">#000005c1</color>
+ <color name="i_am_color_5c2">#000005c2</color>
+ <color name="i_am_color_5c3">#000005c3</color>
+ <color name="i_am_color_5c4">#000005c4</color>
+ <color name="i_am_color_5c5">#000005c5</color>
+ <color name="i_am_color_5c6">#000005c6</color>
+ <color name="i_am_color_5c7">#000005c7</color>
+ <color name="i_am_color_5c8">#000005c8</color>
+ <color name="i_am_color_5c9">#000005c9</color>
+ <color name="i_am_color_5ca">#000005ca</color>
+ <color name="i_am_color_5cb">#000005cb</color>
+ <color name="i_am_color_5cc">#000005cc</color>
+ <color name="i_am_color_5cd">#000005cd</color>
+ <color name="i_am_color_5ce">#000005ce</color>
+ <color name="i_am_color_5cf">#000005cf</color>
+ <color name="i_am_color_5d0">#000005d0</color>
+ <color name="i_am_color_5d1">#000005d1</color>
+ <color name="i_am_color_5d2">#000005d2</color>
+ <color name="i_am_color_5d3">#000005d3</color>
+ <color name="i_am_color_5d4">#000005d4</color>
+ <color name="i_am_color_5d5">#000005d5</color>
+ <color name="i_am_color_5d6">#000005d6</color>
+ <color name="i_am_color_5d7">#000005d7</color>
+ <color name="i_am_color_5d8">#000005d8</color>
+ <color name="i_am_color_5d9">#000005d9</color>
+ <color name="i_am_color_5da">#000005da</color>
+ <color name="i_am_color_5db">#000005db</color>
+ <color name="i_am_color_5dc">#000005dc</color>
+ <color name="i_am_color_5dd">#000005dd</color>
+ <color name="i_am_color_5de">#000005de</color>
+ <color name="i_am_color_5df">#000005df</color>
+ <color name="i_am_color_5e0">#000005e0</color>
+ <color name="i_am_color_5e1">#000005e1</color>
+ <color name="i_am_color_5e2">#000005e2</color>
+ <color name="i_am_color_5e3">#000005e3</color>
+ <color name="i_am_color_5e4">#000005e4</color>
+ <color name="i_am_color_5e5">#000005e5</color>
+ <color name="i_am_color_5e6">#000005e6</color>
+ <color name="i_am_color_5e7">#000005e7</color>
+ <color name="i_am_color_5e8">#000005e8</color>
+ <color name="i_am_color_5e9">#000005e9</color>
+ <color name="i_am_color_5ea">#000005ea</color>
+ <color name="i_am_color_5eb">#000005eb</color>
+ <color name="i_am_color_5ec">#000005ec</color>
+ <color name="i_am_color_5ed">#000005ed</color>
+ <color name="i_am_color_5ee">#000005ee</color>
+ <color name="i_am_color_5ef">#000005ef</color>
+ <color name="i_am_color_5f0">#000005f0</color>
+ <color name="i_am_color_5f1">#000005f1</color>
+ <color name="i_am_color_5f2">#000005f2</color>
+ <color name="i_am_color_5f3">#000005f3</color>
+ <color name="i_am_color_5f4">#000005f4</color>
+ <color name="i_am_color_5f5">#000005f5</color>
+ <color name="i_am_color_5f6">#000005f6</color>
+ <color name="i_am_color_5f7">#000005f7</color>
+ <color name="i_am_color_5f8">#000005f8</color>
+ <color name="i_am_color_5f9">#000005f9</color>
+ <color name="i_am_color_5fa">#000005fa</color>
+ <color name="i_am_color_5fb">#000005fb</color>
+ <color name="i_am_color_5fc">#000005fc</color>
+ <color name="i_am_color_5fd">#000005fd</color>
+ <color name="i_am_color_5fe">#000005fe</color>
+ <color name="i_am_color_5ff">#000005ff</color>
+ <color name="i_am_color_600">#00000600</color>
+ <color name="i_am_color_601">#00000601</color>
+ <color name="i_am_color_602">#00000602</color>
+ <color name="i_am_color_603">#00000603</color>
+ <color name="i_am_color_604">#00000604</color>
+ <color name="i_am_color_605">#00000605</color>
+ <color name="i_am_color_606">#00000606</color>
+ <color name="i_am_color_607">#00000607</color>
+ <color name="i_am_color_608">#00000608</color>
+ <color name="i_am_color_609">#00000609</color>
+ <color name="i_am_color_60a">#0000060a</color>
+ <color name="i_am_color_60b">#0000060b</color>
+ <color name="i_am_color_60c">#0000060c</color>
+ <color name="i_am_color_60d">#0000060d</color>
+ <color name="i_am_color_60e">#0000060e</color>
+ <color name="i_am_color_60f">#0000060f</color>
+ <color name="i_am_color_610">#00000610</color>
+ <color name="i_am_color_611">#00000611</color>
+ <color name="i_am_color_612">#00000612</color>
+ <color name="i_am_color_613">#00000613</color>
+ <color name="i_am_color_614">#00000614</color>
+ <color name="i_am_color_615">#00000615</color>
+ <color name="i_am_color_616">#00000616</color>
+ <color name="i_am_color_617">#00000617</color>
+ <color name="i_am_color_618">#00000618</color>
+ <color name="i_am_color_619">#00000619</color>
+ <color name="i_am_color_61a">#0000061a</color>
+ <color name="i_am_color_61b">#0000061b</color>
+ <color name="i_am_color_61c">#0000061c</color>
+ <color name="i_am_color_61d">#0000061d</color>
+ <color name="i_am_color_61e">#0000061e</color>
+ <color name="i_am_color_61f">#0000061f</color>
+ <color name="i_am_color_620">#00000620</color>
+ <color name="i_am_color_621">#00000621</color>
+ <color name="i_am_color_622">#00000622</color>
+ <color name="i_am_color_623">#00000623</color>
+ <color name="i_am_color_624">#00000624</color>
+ <color name="i_am_color_625">#00000625</color>
+ <color name="i_am_color_626">#00000626</color>
+ <color name="i_am_color_627">#00000627</color>
+ <color name="i_am_color_628">#00000628</color>
+ <color name="i_am_color_629">#00000629</color>
+ <color name="i_am_color_62a">#0000062a</color>
+ <color name="i_am_color_62b">#0000062b</color>
+ <color name="i_am_color_62c">#0000062c</color>
+ <color name="i_am_color_62d">#0000062d</color>
+ <color name="i_am_color_62e">#0000062e</color>
+ <color name="i_am_color_62f">#0000062f</color>
+ <color name="i_am_color_630">#00000630</color>
+ <color name="i_am_color_631">#00000631</color>
+ <color name="i_am_color_632">#00000632</color>
+ <color name="i_am_color_633">#00000633</color>
+ <color name="i_am_color_634">#00000634</color>
+ <color name="i_am_color_635">#00000635</color>
+ <color name="i_am_color_636">#00000636</color>
+ <color name="i_am_color_637">#00000637</color>
+ <color name="i_am_color_638">#00000638</color>
+ <color name="i_am_color_639">#00000639</color>
+ <color name="i_am_color_63a">#0000063a</color>
+ <color name="i_am_color_63b">#0000063b</color>
+ <color name="i_am_color_63c">#0000063c</color>
+ <color name="i_am_color_63d">#0000063d</color>
+ <color name="i_am_color_63e">#0000063e</color>
+ <color name="i_am_color_63f">#0000063f</color>
+ <color name="i_am_color_640">#00000640</color>
+ <color name="i_am_color_641">#00000641</color>
+ <color name="i_am_color_642">#00000642</color>
+ <color name="i_am_color_643">#00000643</color>
+ <color name="i_am_color_644">#00000644</color>
+ <color name="i_am_color_645">#00000645</color>
+ <color name="i_am_color_646">#00000646</color>
+ <color name="i_am_color_647">#00000647</color>
+ <color name="i_am_color_648">#00000648</color>
+ <color name="i_am_color_649">#00000649</color>
+ <color name="i_am_color_64a">#0000064a</color>
+ <color name="i_am_color_64b">#0000064b</color>
+ <color name="i_am_color_64c">#0000064c</color>
+ <color name="i_am_color_64d">#0000064d</color>
+ <color name="i_am_color_64e">#0000064e</color>
+ <color name="i_am_color_64f">#0000064f</color>
+ <color name="i_am_color_650">#00000650</color>
+ <color name="i_am_color_651">#00000651</color>
+ <color name="i_am_color_652">#00000652</color>
+ <color name="i_am_color_653">#00000653</color>
+ <color name="i_am_color_654">#00000654</color>
+ <color name="i_am_color_655">#00000655</color>
+ <color name="i_am_color_656">#00000656</color>
+ <color name="i_am_color_657">#00000657</color>
+ <color name="i_am_color_658">#00000658</color>
+ <color name="i_am_color_659">#00000659</color>
+ <color name="i_am_color_65a">#0000065a</color>
+ <color name="i_am_color_65b">#0000065b</color>
+ <color name="i_am_color_65c">#0000065c</color>
+ <color name="i_am_color_65d">#0000065d</color>
+ <color name="i_am_color_65e">#0000065e</color>
+ <color name="i_am_color_65f">#0000065f</color>
+ <color name="i_am_color_660">#00000660</color>
+ <color name="i_am_color_661">#00000661</color>
+ <color name="i_am_color_662">#00000662</color>
+ <color name="i_am_color_663">#00000663</color>
+ <color name="i_am_color_664">#00000664</color>
+ <color name="i_am_color_665">#00000665</color>
+ <color name="i_am_color_666">#00000666</color>
+ <color name="i_am_color_667">#00000667</color>
+ <color name="i_am_color_668">#00000668</color>
+ <color name="i_am_color_669">#00000669</color>
+ <color name="i_am_color_66a">#0000066a</color>
+ <color name="i_am_color_66b">#0000066b</color>
+ <color name="i_am_color_66c">#0000066c</color>
+ <color name="i_am_color_66d">#0000066d</color>
+ <color name="i_am_color_66e">#0000066e</color>
+ <color name="i_am_color_66f">#0000066f</color>
+ <color name="i_am_color_670">#00000670</color>
+ <color name="i_am_color_671">#00000671</color>
+ <color name="i_am_color_672">#00000672</color>
+ <color name="i_am_color_673">#00000673</color>
+ <color name="i_am_color_674">#00000674</color>
+ <color name="i_am_color_675">#00000675</color>
+ <color name="i_am_color_676">#00000676</color>
+ <color name="i_am_color_677">#00000677</color>
+ <color name="i_am_color_678">#00000678</color>
+ <color name="i_am_color_679">#00000679</color>
+ <color name="i_am_color_67a">#0000067a</color>
+ <color name="i_am_color_67b">#0000067b</color>
+ <color name="i_am_color_67c">#0000067c</color>
+ <color name="i_am_color_67d">#0000067d</color>
+ <color name="i_am_color_67e">#0000067e</color>
+ <color name="i_am_color_67f">#0000067f</color>
+ <color name="i_am_color_680">#00000680</color>
+ <color name="i_am_color_681">#00000681</color>
+ <color name="i_am_color_682">#00000682</color>
+ <color name="i_am_color_683">#00000683</color>
+ <color name="i_am_color_684">#00000684</color>
+ <color name="i_am_color_685">#00000685</color>
+ <color name="i_am_color_686">#00000686</color>
+ <color name="i_am_color_687">#00000687</color>
+ <color name="i_am_color_688">#00000688</color>
+ <color name="i_am_color_689">#00000689</color>
+ <color name="i_am_color_68a">#0000068a</color>
+ <color name="i_am_color_68b">#0000068b</color>
+ <color name="i_am_color_68c">#0000068c</color>
+ <color name="i_am_color_68d">#0000068d</color>
+ <color name="i_am_color_68e">#0000068e</color>
+ <color name="i_am_color_68f">#0000068f</color>
+ <color name="i_am_color_690">#00000690</color>
+ <color name="i_am_color_691">#00000691</color>
+ <color name="i_am_color_692">#00000692</color>
+ <color name="i_am_color_693">#00000693</color>
+ <color name="i_am_color_694">#00000694</color>
+ <color name="i_am_color_695">#00000695</color>
+ <color name="i_am_color_696">#00000696</color>
+ <color name="i_am_color_697">#00000697</color>
+ <color name="i_am_color_698">#00000698</color>
+ <color name="i_am_color_699">#00000699</color>
+ <color name="i_am_color_69a">#0000069a</color>
+ <color name="i_am_color_69b">#0000069b</color>
+ <color name="i_am_color_69c">#0000069c</color>
+ <color name="i_am_color_69d">#0000069d</color>
+ <color name="i_am_color_69e">#0000069e</color>
+ <color name="i_am_color_69f">#0000069f</color>
+ <color name="i_am_color_6a0">#000006a0</color>
+ <color name="i_am_color_6a1">#000006a1</color>
+ <color name="i_am_color_6a2">#000006a2</color>
+ <color name="i_am_color_6a3">#000006a3</color>
+ <color name="i_am_color_6a4">#000006a4</color>
+ <color name="i_am_color_6a5">#000006a5</color>
+ <color name="i_am_color_6a6">#000006a6</color>
+ <color name="i_am_color_6a7">#000006a7</color>
+ <color name="i_am_color_6a8">#000006a8</color>
+ <color name="i_am_color_6a9">#000006a9</color>
+ <color name="i_am_color_6aa">#000006aa</color>
+ <color name="i_am_color_6ab">#000006ab</color>
+ <color name="i_am_color_6ac">#000006ac</color>
+ <color name="i_am_color_6ad">#000006ad</color>
+ <color name="i_am_color_6ae">#000006ae</color>
+ <color name="i_am_color_6af">#000006af</color>
+ <color name="i_am_color_6b0">#000006b0</color>
+ <color name="i_am_color_6b1">#000006b1</color>
+ <color name="i_am_color_6b2">#000006b2</color>
+ <color name="i_am_color_6b3">#000006b3</color>
+ <color name="i_am_color_6b4">#000006b4</color>
+ <color name="i_am_color_6b5">#000006b5</color>
+ <color name="i_am_color_6b6">#000006b6</color>
+ <color name="i_am_color_6b7">#000006b7</color>
+ <color name="i_am_color_6b8">#000006b8</color>
+ <color name="i_am_color_6b9">#000006b9</color>
+ <color name="i_am_color_6ba">#000006ba</color>
+ <color name="i_am_color_6bb">#000006bb</color>
+ <color name="i_am_color_6bc">#000006bc</color>
+ <color name="i_am_color_6bd">#000006bd</color>
+ <color name="i_am_color_6be">#000006be</color>
+ <color name="i_am_color_6bf">#000006bf</color>
+ <color name="i_am_color_6c0">#000006c0</color>
+ <color name="i_am_color_6c1">#000006c1</color>
+ <color name="i_am_color_6c2">#000006c2</color>
+ <color name="i_am_color_6c3">#000006c3</color>
+ <color name="i_am_color_6c4">#000006c4</color>
+ <color name="i_am_color_6c5">#000006c5</color>
+ <color name="i_am_color_6c6">#000006c6</color>
+ <color name="i_am_color_6c7">#000006c7</color>
+ <color name="i_am_color_6c8">#000006c8</color>
+ <color name="i_am_color_6c9">#000006c9</color>
+ <color name="i_am_color_6ca">#000006ca</color>
+ <color name="i_am_color_6cb">#000006cb</color>
+ <color name="i_am_color_6cc">#000006cc</color>
+ <color name="i_am_color_6cd">#000006cd</color>
+ <color name="i_am_color_6ce">#000006ce</color>
+ <color name="i_am_color_6cf">#000006cf</color>
+ <color name="i_am_color_6d0">#000006d0</color>
+ <color name="i_am_color_6d1">#000006d1</color>
+ <color name="i_am_color_6d2">#000006d2</color>
+ <color name="i_am_color_6d3">#000006d3</color>
+ <color name="i_am_color_6d4">#000006d4</color>
+ <color name="i_am_color_6d5">#000006d5</color>
+ <color name="i_am_color_6d6">#000006d6</color>
+ <color name="i_am_color_6d7">#000006d7</color>
+ <color name="i_am_color_6d8">#000006d8</color>
+ <color name="i_am_color_6d9">#000006d9</color>
+ <color name="i_am_color_6da">#000006da</color>
+ <color name="i_am_color_6db">#000006db</color>
+ <color name="i_am_color_6dc">#000006dc</color>
+ <color name="i_am_color_6dd">#000006dd</color>
+ <color name="i_am_color_6de">#000006de</color>
+ <color name="i_am_color_6df">#000006df</color>
+ <color name="i_am_color_6e0">#000006e0</color>
+ <color name="i_am_color_6e1">#000006e1</color>
+ <color name="i_am_color_6e2">#000006e2</color>
+ <color name="i_am_color_6e3">#000006e3</color>
+ <color name="i_am_color_6e4">#000006e4</color>
+ <color name="i_am_color_6e5">#000006e5</color>
+ <color name="i_am_color_6e6">#000006e6</color>
+ <color name="i_am_color_6e7">#000006e7</color>
+ <color name="i_am_color_6e8">#000006e8</color>
+ <color name="i_am_color_6e9">#000006e9</color>
+ <color name="i_am_color_6ea">#000006ea</color>
+ <color name="i_am_color_6eb">#000006eb</color>
+ <color name="i_am_color_6ec">#000006ec</color>
+ <color name="i_am_color_6ed">#000006ed</color>
+ <color name="i_am_color_6ee">#000006ee</color>
+ <color name="i_am_color_6ef">#000006ef</color>
+ <color name="i_am_color_6f0">#000006f0</color>
+ <color name="i_am_color_6f1">#000006f1</color>
+ <color name="i_am_color_6f2">#000006f2</color>
+ <color name="i_am_color_6f3">#000006f3</color>
+ <color name="i_am_color_6f4">#000006f4</color>
+ <color name="i_am_color_6f5">#000006f5</color>
+ <color name="i_am_color_6f6">#000006f6</color>
+ <color name="i_am_color_6f7">#000006f7</color>
+ <color name="i_am_color_6f8">#000006f8</color>
+ <color name="i_am_color_6f9">#000006f9</color>
+ <color name="i_am_color_6fa">#000006fa</color>
+ <color name="i_am_color_6fb">#000006fb</color>
+ <color name="i_am_color_6fc">#000006fc</color>
+ <color name="i_am_color_6fd">#000006fd</color>
+ <color name="i_am_color_6fe">#000006fe</color>
+ <color name="i_am_color_6ff">#000006ff</color>
+ <color name="i_am_color_700">#00000700</color>
+ <color name="i_am_color_701">#00000701</color>
+ <color name="i_am_color_702">#00000702</color>
+ <color name="i_am_color_703">#00000703</color>
+ <color name="i_am_color_704">#00000704</color>
+ <color name="i_am_color_705">#00000705</color>
+ <color name="i_am_color_706">#00000706</color>
+ <color name="i_am_color_707">#00000707</color>
+ <color name="i_am_color_708">#00000708</color>
+ <color name="i_am_color_709">#00000709</color>
+ <color name="i_am_color_70a">#0000070a</color>
+ <color name="i_am_color_70b">#0000070b</color>
+ <color name="i_am_color_70c">#0000070c</color>
+ <color name="i_am_color_70d">#0000070d</color>
+ <color name="i_am_color_70e">#0000070e</color>
+ <color name="i_am_color_70f">#0000070f</color>
+ <color name="i_am_color_710">#00000710</color>
+ <color name="i_am_color_711">#00000711</color>
+ <color name="i_am_color_712">#00000712</color>
+ <color name="i_am_color_713">#00000713</color>
+ <color name="i_am_color_714">#00000714</color>
+ <color name="i_am_color_715">#00000715</color>
+ <color name="i_am_color_716">#00000716</color>
+ <color name="i_am_color_717">#00000717</color>
+ <color name="i_am_color_718">#00000718</color>
+ <color name="i_am_color_719">#00000719</color>
+ <color name="i_am_color_71a">#0000071a</color>
+ <color name="i_am_color_71b">#0000071b</color>
+ <color name="i_am_color_71c">#0000071c</color>
+ <color name="i_am_color_71d">#0000071d</color>
+ <color name="i_am_color_71e">#0000071e</color>
+ <color name="i_am_color_71f">#0000071f</color>
+ <color name="i_am_color_720">#00000720</color>
+ <color name="i_am_color_721">#00000721</color>
+ <color name="i_am_color_722">#00000722</color>
+ <color name="i_am_color_723">#00000723</color>
+ <color name="i_am_color_724">#00000724</color>
+ <color name="i_am_color_725">#00000725</color>
+ <color name="i_am_color_726">#00000726</color>
+ <color name="i_am_color_727">#00000727</color>
+ <color name="i_am_color_728">#00000728</color>
+ <color name="i_am_color_729">#00000729</color>
+ <color name="i_am_color_72a">#0000072a</color>
+ <color name="i_am_color_72b">#0000072b</color>
+ <color name="i_am_color_72c">#0000072c</color>
+ <color name="i_am_color_72d">#0000072d</color>
+ <color name="i_am_color_72e">#0000072e</color>
+ <color name="i_am_color_72f">#0000072f</color>
+ <color name="i_am_color_730">#00000730</color>
+ <color name="i_am_color_731">#00000731</color>
+ <color name="i_am_color_732">#00000732</color>
+ <color name="i_am_color_733">#00000733</color>
+ <color name="i_am_color_734">#00000734</color>
+ <color name="i_am_color_735">#00000735</color>
+ <color name="i_am_color_736">#00000736</color>
+ <color name="i_am_color_737">#00000737</color>
+ <color name="i_am_color_738">#00000738</color>
+ <color name="i_am_color_739">#00000739</color>
+ <color name="i_am_color_73a">#0000073a</color>
+ <color name="i_am_color_73b">#0000073b</color>
+ <color name="i_am_color_73c">#0000073c</color>
+ <color name="i_am_color_73d">#0000073d</color>
+ <color name="i_am_color_73e">#0000073e</color>
+ <color name="i_am_color_73f">#0000073f</color>
+ <color name="i_am_color_740">#00000740</color>
+ <color name="i_am_color_741">#00000741</color>
+ <color name="i_am_color_742">#00000742</color>
+ <color name="i_am_color_743">#00000743</color>
+ <color name="i_am_color_744">#00000744</color>
+ <color name="i_am_color_745">#00000745</color>
+ <color name="i_am_color_746">#00000746</color>
+ <color name="i_am_color_747">#00000747</color>
+ <color name="i_am_color_748">#00000748</color>
+ <color name="i_am_color_749">#00000749</color>
+ <color name="i_am_color_74a">#0000074a</color>
+ <color name="i_am_color_74b">#0000074b</color>
+ <color name="i_am_color_74c">#0000074c</color>
+ <color name="i_am_color_74d">#0000074d</color>
+ <color name="i_am_color_74e">#0000074e</color>
+ <color name="i_am_color_74f">#0000074f</color>
+ <color name="i_am_color_750">#00000750</color>
+ <color name="i_am_color_751">#00000751</color>
+ <color name="i_am_color_752">#00000752</color>
+ <color name="i_am_color_753">#00000753</color>
+ <color name="i_am_color_754">#00000754</color>
+ <color name="i_am_color_755">#00000755</color>
+ <color name="i_am_color_756">#00000756</color>
+ <color name="i_am_color_757">#00000757</color>
+ <color name="i_am_color_758">#00000758</color>
+ <color name="i_am_color_759">#00000759</color>
+ <color name="i_am_color_75a">#0000075a</color>
+ <color name="i_am_color_75b">#0000075b</color>
+ <color name="i_am_color_75c">#0000075c</color>
+ <color name="i_am_color_75d">#0000075d</color>
+ <color name="i_am_color_75e">#0000075e</color>
+ <color name="i_am_color_75f">#0000075f</color>
+ <color name="i_am_color_760">#00000760</color>
+ <color name="i_am_color_761">#00000761</color>
+ <color name="i_am_color_762">#00000762</color>
+ <color name="i_am_color_763">#00000763</color>
+ <color name="i_am_color_764">#00000764</color>
+ <color name="i_am_color_765">#00000765</color>
+ <color name="i_am_color_766">#00000766</color>
+ <color name="i_am_color_767">#00000767</color>
+ <color name="i_am_color_768">#00000768</color>
+ <color name="i_am_color_769">#00000769</color>
+ <color name="i_am_color_76a">#0000076a</color>
+ <color name="i_am_color_76b">#0000076b</color>
+ <color name="i_am_color_76c">#0000076c</color>
+ <color name="i_am_color_76d">#0000076d</color>
+ <color name="i_am_color_76e">#0000076e</color>
+ <color name="i_am_color_76f">#0000076f</color>
+ <color name="i_am_color_770">#00000770</color>
+ <color name="i_am_color_771">#00000771</color>
+ <color name="i_am_color_772">#00000772</color>
+ <color name="i_am_color_773">#00000773</color>
+ <color name="i_am_color_774">#00000774</color>
+ <color name="i_am_color_775">#00000775</color>
+ <color name="i_am_color_776">#00000776</color>
+ <color name="i_am_color_777">#00000777</color>
+ <color name="i_am_color_778">#00000778</color>
+ <color name="i_am_color_779">#00000779</color>
+ <color name="i_am_color_77a">#0000077a</color>
+ <color name="i_am_color_77b">#0000077b</color>
+ <color name="i_am_color_77c">#0000077c</color>
+ <color name="i_am_color_77d">#0000077d</color>
+ <color name="i_am_color_77e">#0000077e</color>
+ <color name="i_am_color_77f">#0000077f</color>
+ <color name="i_am_color_780">#00000780</color>
+ <color name="i_am_color_781">#00000781</color>
+ <color name="i_am_color_782">#00000782</color>
+ <color name="i_am_color_783">#00000783</color>
+ <color name="i_am_color_784">#00000784</color>
+ <color name="i_am_color_785">#00000785</color>
+ <color name="i_am_color_786">#00000786</color>
+ <color name="i_am_color_787">#00000787</color>
+ <color name="i_am_color_788">#00000788</color>
+ <color name="i_am_color_789">#00000789</color>
+ <color name="i_am_color_78a">#0000078a</color>
+ <color name="i_am_color_78b">#0000078b</color>
+ <color name="i_am_color_78c">#0000078c</color>
+ <color name="i_am_color_78d">#0000078d</color>
+ <color name="i_am_color_78e">#0000078e</color>
+ <color name="i_am_color_78f">#0000078f</color>
+ <color name="i_am_color_790">#00000790</color>
+ <color name="i_am_color_791">#00000791</color>
+ <color name="i_am_color_792">#00000792</color>
+ <color name="i_am_color_793">#00000793</color>
+ <color name="i_am_color_794">#00000794</color>
+ <color name="i_am_color_795">#00000795</color>
+ <color name="i_am_color_796">#00000796</color>
+ <color name="i_am_color_797">#00000797</color>
+ <color name="i_am_color_798">#00000798</color>
+ <color name="i_am_color_799">#00000799</color>
+ <color name="i_am_color_79a">#0000079a</color>
+ <color name="i_am_color_79b">#0000079b</color>
+ <color name="i_am_color_79c">#0000079c</color>
+ <color name="i_am_color_79d">#0000079d</color>
+ <color name="i_am_color_79e">#0000079e</color>
+ <color name="i_am_color_79f">#0000079f</color>
+ <color name="i_am_color_7a0">#000007a0</color>
+ <color name="i_am_color_7a1">#000007a1</color>
+ <color name="i_am_color_7a2">#000007a2</color>
+ <color name="i_am_color_7a3">#000007a3</color>
+ <color name="i_am_color_7a4">#000007a4</color>
+ <color name="i_am_color_7a5">#000007a5</color>
+ <color name="i_am_color_7a6">#000007a6</color>
+ <color name="i_am_color_7a7">#000007a7</color>
+ <color name="i_am_color_7a8">#000007a8</color>
+ <color name="i_am_color_7a9">#000007a9</color>
+ <color name="i_am_color_7aa">#000007aa</color>
+ <color name="i_am_color_7ab">#000007ab</color>
+ <color name="i_am_color_7ac">#000007ac</color>
+ <color name="i_am_color_7ad">#000007ad</color>
+ <color name="i_am_color_7ae">#000007ae</color>
+ <color name="i_am_color_7af">#000007af</color>
+ <color name="i_am_color_7b0">#000007b0</color>
+ <color name="i_am_color_7b1">#000007b1</color>
+ <color name="i_am_color_7b2">#000007b2</color>
+ <color name="i_am_color_7b3">#000007b3</color>
+ <color name="i_am_color_7b4">#000007b4</color>
+ <color name="i_am_color_7b5">#000007b5</color>
+ <color name="i_am_color_7b6">#000007b6</color>
+ <color name="i_am_color_7b7">#000007b7</color>
+ <color name="i_am_color_7b8">#000007b8</color>
+ <color name="i_am_color_7b9">#000007b9</color>
+ <color name="i_am_color_7ba">#000007ba</color>
+ <color name="i_am_color_7bb">#000007bb</color>
+ <color name="i_am_color_7bc">#000007bc</color>
+ <color name="i_am_color_7bd">#000007bd</color>
+ <color name="i_am_color_7be">#000007be</color>
+ <color name="i_am_color_7bf">#000007bf</color>
+ <color name="i_am_color_7c0">#000007c0</color>
+ <color name="i_am_color_7c1">#000007c1</color>
+ <color name="i_am_color_7c2">#000007c2</color>
+ <color name="i_am_color_7c3">#000007c3</color>
+ <color name="i_am_color_7c4">#000007c4</color>
+ <color name="i_am_color_7c5">#000007c5</color>
+ <color name="i_am_color_7c6">#000007c6</color>
+ <color name="i_am_color_7c7">#000007c7</color>
+ <color name="i_am_color_7c8">#000007c8</color>
+ <color name="i_am_color_7c9">#000007c9</color>
+ <color name="i_am_color_7ca">#000007ca</color>
+ <color name="i_am_color_7cb">#000007cb</color>
+ <color name="i_am_color_7cc">#000007cc</color>
+ <color name="i_am_color_7cd">#000007cd</color>
+ <color name="i_am_color_7ce">#000007ce</color>
+ <color name="i_am_color_7cf">#000007cf</color>
+ <color name="i_am_color_7d0">#000007d0</color>
+ <color name="i_am_color_7d1">#000007d1</color>
+ <color name="i_am_color_7d2">#000007d2</color>
+ <color name="i_am_color_7d3">#000007d3</color>
+ <color name="i_am_color_7d4">#000007d4</color>
+ <color name="i_am_color_7d5">#000007d5</color>
+ <color name="i_am_color_7d6">#000007d6</color>
+ <color name="i_am_color_7d7">#000007d7</color>
+ <color name="i_am_color_7d8">#000007d8</color>
+ <color name="i_am_color_7d9">#000007d9</color>
+ <color name="i_am_color_7da">#000007da</color>
+ <color name="i_am_color_7db">#000007db</color>
+ <color name="i_am_color_7dc">#000007dc</color>
+ <color name="i_am_color_7dd">#000007dd</color>
+ <color name="i_am_color_7de">#000007de</color>
+ <color name="i_am_color_7df">#000007df</color>
+ <color name="i_am_color_7e0">#000007e0</color>
+ <color name="i_am_color_7e1">#000007e1</color>
+ <color name="i_am_color_7e2">#000007e2</color>
+ <color name="i_am_color_7e3">#000007e3</color>
+ <color name="i_am_color_7e4">#000007e4</color>
+ <color name="i_am_color_7e5">#000007e5</color>
+ <color name="i_am_color_7e6">#000007e6</color>
+ <color name="i_am_color_7e7">#000007e7</color>
+ <color name="i_am_color_7e8">#000007e8</color>
+ <color name="i_am_color_7e9">#000007e9</color>
+ <color name="i_am_color_7ea">#000007ea</color>
+ <color name="i_am_color_7eb">#000007eb</color>
+ <color name="i_am_color_7ec">#000007ec</color>
+ <color name="i_am_color_7ed">#000007ed</color>
+ <color name="i_am_color_7ee">#000007ee</color>
+ <color name="i_am_color_7ef">#000007ef</color>
+ <color name="i_am_color_7f0">#000007f0</color>
+ <color name="i_am_color_7f1">#000007f1</color>
+ <color name="i_am_color_7f2">#000007f2</color>
+ <color name="i_am_color_7f3">#000007f3</color>
+ <color name="i_am_color_7f4">#000007f4</color>
+ <color name="i_am_color_7f5">#000007f5</color>
+ <color name="i_am_color_7f6">#000007f6</color>
+ <color name="i_am_color_7f7">#000007f7</color>
+ <color name="i_am_color_7f8">#000007f8</color>
+ <color name="i_am_color_7f9">#000007f9</color>
+ <color name="i_am_color_7fa">#000007fa</color>
+ <color name="i_am_color_7fb">#000007fb</color>
+ <color name="i_am_color_7fc">#000007fc</color>
+ <color name="i_am_color_7fd">#000007fd</color>
+ <color name="i_am_color_7fe">#000007fe</color>
+ <color name="i_am_color_7ff">#000007ff</color>
+ <color name="i_am_color_800">#00000800</color>
+ <color name="i_am_color_801">#00000801</color>
+ <color name="i_am_color_802">#00000802</color>
+ <color name="i_am_color_803">#00000803</color>
+ <color name="i_am_color_804">#00000804</color>
+ <color name="i_am_color_805">#00000805</color>
+ <color name="i_am_color_806">#00000806</color>
+ <color name="i_am_color_807">#00000807</color>
+ <color name="i_am_color_808">#00000808</color>
+ <color name="i_am_color_809">#00000809</color>
+ <color name="i_am_color_80a">#0000080a</color>
+ <color name="i_am_color_80b">#0000080b</color>
+ <color name="i_am_color_80c">#0000080c</color>
+ <color name="i_am_color_80d">#0000080d</color>
+ <color name="i_am_color_80e">#0000080e</color>
+ <color name="i_am_color_80f">#0000080f</color>
+ <color name="i_am_color_810">#00000810</color>
+ <color name="i_am_color_811">#00000811</color>
+ <color name="i_am_color_812">#00000812</color>
+ <color name="i_am_color_813">#00000813</color>
+ <color name="i_am_color_814">#00000814</color>
+ <color name="i_am_color_815">#00000815</color>
+ <color name="i_am_color_816">#00000816</color>
+ <color name="i_am_color_817">#00000817</color>
+ <color name="i_am_color_818">#00000818</color>
+ <color name="i_am_color_819">#00000819</color>
+ <color name="i_am_color_81a">#0000081a</color>
+ <color name="i_am_color_81b">#0000081b</color>
+ <color name="i_am_color_81c">#0000081c</color>
+ <color name="i_am_color_81d">#0000081d</color>
+ <color name="i_am_color_81e">#0000081e</color>
+ <color name="i_am_color_81f">#0000081f</color>
+ <color name="i_am_color_820">#00000820</color>
+ <color name="i_am_color_821">#00000821</color>
+ <color name="i_am_color_822">#00000822</color>
+ <color name="i_am_color_823">#00000823</color>
+ <color name="i_am_color_824">#00000824</color>
+ <color name="i_am_color_825">#00000825</color>
+ <color name="i_am_color_826">#00000826</color>
+ <color name="i_am_color_827">#00000827</color>
+ <color name="i_am_color_828">#00000828</color>
+ <color name="i_am_color_829">#00000829</color>
+ <color name="i_am_color_82a">#0000082a</color>
+ <color name="i_am_color_82b">#0000082b</color>
+ <color name="i_am_color_82c">#0000082c</color>
+ <color name="i_am_color_82d">#0000082d</color>
+ <color name="i_am_color_82e">#0000082e</color>
+ <color name="i_am_color_82f">#0000082f</color>
+ <color name="i_am_color_830">#00000830</color>
+ <color name="i_am_color_831">#00000831</color>
+ <color name="i_am_color_832">#00000832</color>
+ <color name="i_am_color_833">#00000833</color>
+ <color name="i_am_color_834">#00000834</color>
+ <color name="i_am_color_835">#00000835</color>
+ <color name="i_am_color_836">#00000836</color>
+ <color name="i_am_color_837">#00000837</color>
+ <color name="i_am_color_838">#00000838</color>
+ <color name="i_am_color_839">#00000839</color>
+ <color name="i_am_color_83a">#0000083a</color>
+ <color name="i_am_color_83b">#0000083b</color>
+ <color name="i_am_color_83c">#0000083c</color>
+ <color name="i_am_color_83d">#0000083d</color>
+ <color name="i_am_color_83e">#0000083e</color>
+ <color name="i_am_color_83f">#0000083f</color>
+ <color name="i_am_color_840">#00000840</color>
+ <color name="i_am_color_841">#00000841</color>
+ <color name="i_am_color_842">#00000842</color>
+ <color name="i_am_color_843">#00000843</color>
+ <color name="i_am_color_844">#00000844</color>
+ <color name="i_am_color_845">#00000845</color>
+ <color name="i_am_color_846">#00000846</color>
+ <color name="i_am_color_847">#00000847</color>
+ <color name="i_am_color_848">#00000848</color>
+ <color name="i_am_color_849">#00000849</color>
+ <color name="i_am_color_84a">#0000084a</color>
+ <color name="i_am_color_84b">#0000084b</color>
+ <color name="i_am_color_84c">#0000084c</color>
+ <color name="i_am_color_84d">#0000084d</color>
+ <color name="i_am_color_84e">#0000084e</color>
+ <color name="i_am_color_84f">#0000084f</color>
+ <color name="i_am_color_850">#00000850</color>
+ <color name="i_am_color_851">#00000851</color>
+ <color name="i_am_color_852">#00000852</color>
+ <color name="i_am_color_853">#00000853</color>
+ <color name="i_am_color_854">#00000854</color>
+ <color name="i_am_color_855">#00000855</color>
+ <color name="i_am_color_856">#00000856</color>
+ <color name="i_am_color_857">#00000857</color>
+ <color name="i_am_color_858">#00000858</color>
+ <color name="i_am_color_859">#00000859</color>
+ <color name="i_am_color_85a">#0000085a</color>
+ <color name="i_am_color_85b">#0000085b</color>
+ <color name="i_am_color_85c">#0000085c</color>
+ <color name="i_am_color_85d">#0000085d</color>
+ <color name="i_am_color_85e">#0000085e</color>
+ <color name="i_am_color_85f">#0000085f</color>
+ <color name="i_am_color_860">#00000860</color>
+ <color name="i_am_color_861">#00000861</color>
+ <color name="i_am_color_862">#00000862</color>
+ <color name="i_am_color_863">#00000863</color>
+ <color name="i_am_color_864">#00000864</color>
+ <color name="i_am_color_865">#00000865</color>
+ <color name="i_am_color_866">#00000866</color>
+ <color name="i_am_color_867">#00000867</color>
+ <color name="i_am_color_868">#00000868</color>
+ <color name="i_am_color_869">#00000869</color>
+ <color name="i_am_color_86a">#0000086a</color>
+ <color name="i_am_color_86b">#0000086b</color>
+ <color name="i_am_color_86c">#0000086c</color>
+ <color name="i_am_color_86d">#0000086d</color>
+ <color name="i_am_color_86e">#0000086e</color>
+ <color name="i_am_color_86f">#0000086f</color>
+ <color name="i_am_color_870">#00000870</color>
+ <color name="i_am_color_871">#00000871</color>
+ <color name="i_am_color_872">#00000872</color>
+ <color name="i_am_color_873">#00000873</color>
+ <color name="i_am_color_874">#00000874</color>
+ <color name="i_am_color_875">#00000875</color>
+ <color name="i_am_color_876">#00000876</color>
+ <color name="i_am_color_877">#00000877</color>
+ <color name="i_am_color_878">#00000878</color>
+ <color name="i_am_color_879">#00000879</color>
+ <color name="i_am_color_87a">#0000087a</color>
+ <color name="i_am_color_87b">#0000087b</color>
+ <color name="i_am_color_87c">#0000087c</color>
+ <color name="i_am_color_87d">#0000087d</color>
+ <color name="i_am_color_87e">#0000087e</color>
+ <color name="i_am_color_87f">#0000087f</color>
+ <color name="i_am_color_880">#00000880</color>
+ <color name="i_am_color_881">#00000881</color>
+ <color name="i_am_color_882">#00000882</color>
+ <color name="i_am_color_883">#00000883</color>
+ <color name="i_am_color_884">#00000884</color>
+ <color name="i_am_color_885">#00000885</color>
+ <color name="i_am_color_886">#00000886</color>
+ <color name="i_am_color_887">#00000887</color>
+ <color name="i_am_color_888">#00000888</color>
+ <color name="i_am_color_889">#00000889</color>
+ <color name="i_am_color_88a">#0000088a</color>
+ <color name="i_am_color_88b">#0000088b</color>
+ <color name="i_am_color_88c">#0000088c</color>
+ <color name="i_am_color_88d">#0000088d</color>
+ <color name="i_am_color_88e">#0000088e</color>
+ <color name="i_am_color_88f">#0000088f</color>
+ <color name="i_am_color_890">#00000890</color>
+ <color name="i_am_color_891">#00000891</color>
+ <color name="i_am_color_892">#00000892</color>
+ <color name="i_am_color_893">#00000893</color>
+ <color name="i_am_color_894">#00000894</color>
+ <color name="i_am_color_895">#00000895</color>
+ <color name="i_am_color_896">#00000896</color>
+ <color name="i_am_color_897">#00000897</color>
+ <color name="i_am_color_898">#00000898</color>
+ <color name="i_am_color_899">#00000899</color>
+ <color name="i_am_color_89a">#0000089a</color>
+ <color name="i_am_color_89b">#0000089b</color>
+ <color name="i_am_color_89c">#0000089c</color>
+ <color name="i_am_color_89d">#0000089d</color>
+ <color name="i_am_color_89e">#0000089e</color>
+ <color name="i_am_color_89f">#0000089f</color>
+ <color name="i_am_color_8a0">#000008a0</color>
+ <color name="i_am_color_8a1">#000008a1</color>
+ <color name="i_am_color_8a2">#000008a2</color>
+ <color name="i_am_color_8a3">#000008a3</color>
+ <color name="i_am_color_8a4">#000008a4</color>
+ <color name="i_am_color_8a5">#000008a5</color>
+ <color name="i_am_color_8a6">#000008a6</color>
+ <color name="i_am_color_8a7">#000008a7</color>
+ <color name="i_am_color_8a8">#000008a8</color>
+ <color name="i_am_color_8a9">#000008a9</color>
+ <color name="i_am_color_8aa">#000008aa</color>
+ <color name="i_am_color_8ab">#000008ab</color>
+ <color name="i_am_color_8ac">#000008ac</color>
+ <color name="i_am_color_8ad">#000008ad</color>
+ <color name="i_am_color_8ae">#000008ae</color>
+ <color name="i_am_color_8af">#000008af</color>
+ <color name="i_am_color_8b0">#000008b0</color>
+ <color name="i_am_color_8b1">#000008b1</color>
+ <color name="i_am_color_8b2">#000008b2</color>
+ <color name="i_am_color_8b3">#000008b3</color>
+ <color name="i_am_color_8b4">#000008b4</color>
+ <color name="i_am_color_8b5">#000008b5</color>
+ <color name="i_am_color_8b6">#000008b6</color>
+ <color name="i_am_color_8b7">#000008b7</color>
+ <color name="i_am_color_8b8">#000008b8</color>
+ <color name="i_am_color_8b9">#000008b9</color>
+ <color name="i_am_color_8ba">#000008ba</color>
+ <color name="i_am_color_8bb">#000008bb</color>
+ <color name="i_am_color_8bc">#000008bc</color>
+ <color name="i_am_color_8bd">#000008bd</color>
+ <color name="i_am_color_8be">#000008be</color>
+ <color name="i_am_color_8bf">#000008bf</color>
+ <color name="i_am_color_8c0">#000008c0</color>
+ <color name="i_am_color_8c1">#000008c1</color>
+ <color name="i_am_color_8c2">#000008c2</color>
+ <color name="i_am_color_8c3">#000008c3</color>
+ <color name="i_am_color_8c4">#000008c4</color>
+ <color name="i_am_color_8c5">#000008c5</color>
+ <color name="i_am_color_8c6">#000008c6</color>
+ <color name="i_am_color_8c7">#000008c7</color>
+ <color name="i_am_color_8c8">#000008c8</color>
+ <color name="i_am_color_8c9">#000008c9</color>
+ <color name="i_am_color_8ca">#000008ca</color>
+ <color name="i_am_color_8cb">#000008cb</color>
+ <color name="i_am_color_8cc">#000008cc</color>
+ <color name="i_am_color_8cd">#000008cd</color>
+ <color name="i_am_color_8ce">#000008ce</color>
+ <color name="i_am_color_8cf">#000008cf</color>
+ <color name="i_am_color_8d0">#000008d0</color>
+ <color name="i_am_color_8d1">#000008d1</color>
+ <color name="i_am_color_8d2">#000008d2</color>
+ <color name="i_am_color_8d3">#000008d3</color>
+ <color name="i_am_color_8d4">#000008d4</color>
+ <color name="i_am_color_8d5">#000008d5</color>
+ <color name="i_am_color_8d6">#000008d6</color>
+ <color name="i_am_color_8d7">#000008d7</color>
+ <color name="i_am_color_8d8">#000008d8</color>
+ <color name="i_am_color_8d9">#000008d9</color>
+ <color name="i_am_color_8da">#000008da</color>
+ <color name="i_am_color_8db">#000008db</color>
+ <color name="i_am_color_8dc">#000008dc</color>
+ <color name="i_am_color_8dd">#000008dd</color>
+ <color name="i_am_color_8de">#000008de</color>
+ <color name="i_am_color_8df">#000008df</color>
+ <color name="i_am_color_8e0">#000008e0</color>
+ <color name="i_am_color_8e1">#000008e1</color>
+ <color name="i_am_color_8e2">#000008e2</color>
+ <color name="i_am_color_8e3">#000008e3</color>
+ <color name="i_am_color_8e4">#000008e4</color>
+ <color name="i_am_color_8e5">#000008e5</color>
+ <color name="i_am_color_8e6">#000008e6</color>
+ <color name="i_am_color_8e7">#000008e7</color>
+ <color name="i_am_color_8e8">#000008e8</color>
+ <color name="i_am_color_8e9">#000008e9</color>
+ <color name="i_am_color_8ea">#000008ea</color>
+ <color name="i_am_color_8eb">#000008eb</color>
+ <color name="i_am_color_8ec">#000008ec</color>
+ <color name="i_am_color_8ed">#000008ed</color>
+ <color name="i_am_color_8ee">#000008ee</color>
+ <color name="i_am_color_8ef">#000008ef</color>
+ <color name="i_am_color_8f0">#000008f0</color>
+ <color name="i_am_color_8f1">#000008f1</color>
+ <color name="i_am_color_8f2">#000008f2</color>
+ <color name="i_am_color_8f3">#000008f3</color>
+ <color name="i_am_color_8f4">#000008f4</color>
+ <color name="i_am_color_8f5">#000008f5</color>
+ <color name="i_am_color_8f6">#000008f6</color>
+ <color name="i_am_color_8f7">#000008f7</color>
+ <color name="i_am_color_8f8">#000008f8</color>
+ <color name="i_am_color_8f9">#000008f9</color>
+ <color name="i_am_color_8fa">#000008fa</color>
+ <color name="i_am_color_8fb">#000008fb</color>
+ <color name="i_am_color_8fc">#000008fc</color>
+ <color name="i_am_color_8fd">#000008fd</color>
+ <color name="i_am_color_8fe">#000008fe</color>
+ <color name="i_am_color_8ff">#000008ff</color>
+ <color name="i_am_color_900">#00000900</color>
+ <color name="i_am_color_901">#00000901</color>
+ <color name="i_am_color_902">#00000902</color>
+ <color name="i_am_color_903">#00000903</color>
+ <color name="i_am_color_904">#00000904</color>
+ <color name="i_am_color_905">#00000905</color>
+ <color name="i_am_color_906">#00000906</color>
+ <color name="i_am_color_907">#00000907</color>
+ <color name="i_am_color_908">#00000908</color>
+ <color name="i_am_color_909">#00000909</color>
+ <color name="i_am_color_90a">#0000090a</color>
+ <color name="i_am_color_90b">#0000090b</color>
+ <color name="i_am_color_90c">#0000090c</color>
+ <color name="i_am_color_90d">#0000090d</color>
+ <color name="i_am_color_90e">#0000090e</color>
+ <color name="i_am_color_90f">#0000090f</color>
+ <color name="i_am_color_910">#00000910</color>
+ <color name="i_am_color_911">#00000911</color>
+ <color name="i_am_color_912">#00000912</color>
+ <color name="i_am_color_913">#00000913</color>
+ <color name="i_am_color_914">#00000914</color>
+ <color name="i_am_color_915">#00000915</color>
+ <color name="i_am_color_916">#00000916</color>
+ <color name="i_am_color_917">#00000917</color>
+ <color name="i_am_color_918">#00000918</color>
+ <color name="i_am_color_919">#00000919</color>
+ <color name="i_am_color_91a">#0000091a</color>
+ <color name="i_am_color_91b">#0000091b</color>
+ <color name="i_am_color_91c">#0000091c</color>
+ <color name="i_am_color_91d">#0000091d</color>
+ <color name="i_am_color_91e">#0000091e</color>
+ <color name="i_am_color_91f">#0000091f</color>
+ <color name="i_am_color_920">#00000920</color>
+ <color name="i_am_color_921">#00000921</color>
+ <color name="i_am_color_922">#00000922</color>
+ <color name="i_am_color_923">#00000923</color>
+ <color name="i_am_color_924">#00000924</color>
+ <color name="i_am_color_925">#00000925</color>
+ <color name="i_am_color_926">#00000926</color>
+ <color name="i_am_color_927">#00000927</color>
+ <color name="i_am_color_928">#00000928</color>
+ <color name="i_am_color_929">#00000929</color>
+ <color name="i_am_color_92a">#0000092a</color>
+ <color name="i_am_color_92b">#0000092b</color>
+ <color name="i_am_color_92c">#0000092c</color>
+ <color name="i_am_color_92d">#0000092d</color>
+ <color name="i_am_color_92e">#0000092e</color>
+ <color name="i_am_color_92f">#0000092f</color>
+ <color name="i_am_color_930">#00000930</color>
+ <color name="i_am_color_931">#00000931</color>
+ <color name="i_am_color_932">#00000932</color>
+ <color name="i_am_color_933">#00000933</color>
+ <color name="i_am_color_934">#00000934</color>
+ <color name="i_am_color_935">#00000935</color>
+ <color name="i_am_color_936">#00000936</color>
+ <color name="i_am_color_937">#00000937</color>
+ <color name="i_am_color_938">#00000938</color>
+ <color name="i_am_color_939">#00000939</color>
+ <color name="i_am_color_93a">#0000093a</color>
+ <color name="i_am_color_93b">#0000093b</color>
+ <color name="i_am_color_93c">#0000093c</color>
+ <color name="i_am_color_93d">#0000093d</color>
+ <color name="i_am_color_93e">#0000093e</color>
+ <color name="i_am_color_93f">#0000093f</color>
+ <color name="i_am_color_940">#00000940</color>
+ <color name="i_am_color_941">#00000941</color>
+ <color name="i_am_color_942">#00000942</color>
+ <color name="i_am_color_943">#00000943</color>
+ <color name="i_am_color_944">#00000944</color>
+ <color name="i_am_color_945">#00000945</color>
+ <color name="i_am_color_946">#00000946</color>
+ <color name="i_am_color_947">#00000947</color>
+ <color name="i_am_color_948">#00000948</color>
+ <color name="i_am_color_949">#00000949</color>
+ <color name="i_am_color_94a">#0000094a</color>
+ <color name="i_am_color_94b">#0000094b</color>
+ <color name="i_am_color_94c">#0000094c</color>
+ <color name="i_am_color_94d">#0000094d</color>
+ <color name="i_am_color_94e">#0000094e</color>
+ <color name="i_am_color_94f">#0000094f</color>
+ <color name="i_am_color_950">#00000950</color>
+ <color name="i_am_color_951">#00000951</color>
+ <color name="i_am_color_952">#00000952</color>
+ <color name="i_am_color_953">#00000953</color>
+ <color name="i_am_color_954">#00000954</color>
+ <color name="i_am_color_955">#00000955</color>
+ <color name="i_am_color_956">#00000956</color>
+ <color name="i_am_color_957">#00000957</color>
+ <color name="i_am_color_958">#00000958</color>
+ <color name="i_am_color_959">#00000959</color>
+ <color name="i_am_color_95a">#0000095a</color>
+ <color name="i_am_color_95b">#0000095b</color>
+ <color name="i_am_color_95c">#0000095c</color>
+ <color name="i_am_color_95d">#0000095d</color>
+ <color name="i_am_color_95e">#0000095e</color>
+ <color name="i_am_color_95f">#0000095f</color>
+ <color name="i_am_color_960">#00000960</color>
+ <color name="i_am_color_961">#00000961</color>
+ <color name="i_am_color_962">#00000962</color>
+ <color name="i_am_color_963">#00000963</color>
+ <color name="i_am_color_964">#00000964</color>
+ <color name="i_am_color_965">#00000965</color>
+ <color name="i_am_color_966">#00000966</color>
+ <color name="i_am_color_967">#00000967</color>
+ <color name="i_am_color_968">#00000968</color>
+ <color name="i_am_color_969">#00000969</color>
+ <color name="i_am_color_96a">#0000096a</color>
+ <color name="i_am_color_96b">#0000096b</color>
+ <color name="i_am_color_96c">#0000096c</color>
+ <color name="i_am_color_96d">#0000096d</color>
+ <color name="i_am_color_96e">#0000096e</color>
+ <color name="i_am_color_96f">#0000096f</color>
+ <color name="i_am_color_970">#00000970</color>
+ <color name="i_am_color_971">#00000971</color>
+ <color name="i_am_color_972">#00000972</color>
+ <color name="i_am_color_973">#00000973</color>
+ <color name="i_am_color_974">#00000974</color>
+ <color name="i_am_color_975">#00000975</color>
+ <color name="i_am_color_976">#00000976</color>
+ <color name="i_am_color_977">#00000977</color>
+ <color name="i_am_color_978">#00000978</color>
+ <color name="i_am_color_979">#00000979</color>
+ <color name="i_am_color_97a">#0000097a</color>
+ <color name="i_am_color_97b">#0000097b</color>
+ <color name="i_am_color_97c">#0000097c</color>
+ <color name="i_am_color_97d">#0000097d</color>
+ <color name="i_am_color_97e">#0000097e</color>
+ <color name="i_am_color_97f">#0000097f</color>
+ <color name="i_am_color_980">#00000980</color>
+ <color name="i_am_color_981">#00000981</color>
+ <color name="i_am_color_982">#00000982</color>
+ <color name="i_am_color_983">#00000983</color>
+ <color name="i_am_color_984">#00000984</color>
+ <color name="i_am_color_985">#00000985</color>
+ <color name="i_am_color_986">#00000986</color>
+ <color name="i_am_color_987">#00000987</color>
+ <color name="i_am_color_988">#00000988</color>
+ <color name="i_am_color_989">#00000989</color>
+ <color name="i_am_color_98a">#0000098a</color>
+ <color name="i_am_color_98b">#0000098b</color>
+ <color name="i_am_color_98c">#0000098c</color>
+ <color name="i_am_color_98d">#0000098d</color>
+ <color name="i_am_color_98e">#0000098e</color>
+ <color name="i_am_color_98f">#0000098f</color>
+ <color name="i_am_color_990">#00000990</color>
+ <color name="i_am_color_991">#00000991</color>
+ <color name="i_am_color_992">#00000992</color>
+ <color name="i_am_color_993">#00000993</color>
+ <color name="i_am_color_994">#00000994</color>
+ <color name="i_am_color_995">#00000995</color>
+ <color name="i_am_color_996">#00000996</color>
+ <color name="i_am_color_997">#00000997</color>
+ <color name="i_am_color_998">#00000998</color>
+ <color name="i_am_color_999">#00000999</color>
+ <color name="i_am_color_99a">#0000099a</color>
+ <color name="i_am_color_99b">#0000099b</color>
+ <color name="i_am_color_99c">#0000099c</color>
+ <color name="i_am_color_99d">#0000099d</color>
+ <color name="i_am_color_99e">#0000099e</color>
+ <color name="i_am_color_99f">#0000099f</color>
+ <color name="i_am_color_9a0">#000009a0</color>
+ <color name="i_am_color_9a1">#000009a1</color>
+ <color name="i_am_color_9a2">#000009a2</color>
+ <color name="i_am_color_9a3">#000009a3</color>
+ <color name="i_am_color_9a4">#000009a4</color>
+ <color name="i_am_color_9a5">#000009a5</color>
+ <color name="i_am_color_9a6">#000009a6</color>
+ <color name="i_am_color_9a7">#000009a7</color>
+ <color name="i_am_color_9a8">#000009a8</color>
+ <color name="i_am_color_9a9">#000009a9</color>
+ <color name="i_am_color_9aa">#000009aa</color>
+ <color name="i_am_color_9ab">#000009ab</color>
+ <color name="i_am_color_9ac">#000009ac</color>
+ <color name="i_am_color_9ad">#000009ad</color>
+ <color name="i_am_color_9ae">#000009ae</color>
+ <color name="i_am_color_9af">#000009af</color>
+ <color name="i_am_color_9b0">#000009b0</color>
+ <color name="i_am_color_9b1">#000009b1</color>
+ <color name="i_am_color_9b2">#000009b2</color>
+ <color name="i_am_color_9b3">#000009b3</color>
+ <color name="i_am_color_9b4">#000009b4</color>
+ <color name="i_am_color_9b5">#000009b5</color>
+ <color name="i_am_color_9b6">#000009b6</color>
+ <color name="i_am_color_9b7">#000009b7</color>
+ <color name="i_am_color_9b8">#000009b8</color>
+ <color name="i_am_color_9b9">#000009b9</color>
+ <color name="i_am_color_9ba">#000009ba</color>
+ <color name="i_am_color_9bb">#000009bb</color>
+ <color name="i_am_color_9bc">#000009bc</color>
+ <color name="i_am_color_9bd">#000009bd</color>
+ <color name="i_am_color_9be">#000009be</color>
+ <color name="i_am_color_9bf">#000009bf</color>
+ <color name="i_am_color_9c0">#000009c0</color>
+ <color name="i_am_color_9c1">#000009c1</color>
+ <color name="i_am_color_9c2">#000009c2</color>
+ <color name="i_am_color_9c3">#000009c3</color>
+ <color name="i_am_color_9c4">#000009c4</color>
+ <color name="i_am_color_9c5">#000009c5</color>
+ <color name="i_am_color_9c6">#000009c6</color>
+ <color name="i_am_color_9c7">#000009c7</color>
+ <color name="i_am_color_9c8">#000009c8</color>
+ <color name="i_am_color_9c9">#000009c9</color>
+ <color name="i_am_color_9ca">#000009ca</color>
+ <color name="i_am_color_9cb">#000009cb</color>
+ <color name="i_am_color_9cc">#000009cc</color>
+ <color name="i_am_color_9cd">#000009cd</color>
+ <color name="i_am_color_9ce">#000009ce</color>
+ <color name="i_am_color_9cf">#000009cf</color>
+ <color name="i_am_color_9d0">#000009d0</color>
+ <color name="i_am_color_9d1">#000009d1</color>
+ <color name="i_am_color_9d2">#000009d2</color>
+ <color name="i_am_color_9d3">#000009d3</color>
+ <color name="i_am_color_9d4">#000009d4</color>
+ <color name="i_am_color_9d5">#000009d5</color>
+ <color name="i_am_color_9d6">#000009d6</color>
+ <color name="i_am_color_9d7">#000009d7</color>
+ <color name="i_am_color_9d8">#000009d8</color>
+ <color name="i_am_color_9d9">#000009d9</color>
+ <color name="i_am_color_9da">#000009da</color>
+ <color name="i_am_color_9db">#000009db</color>
+ <color name="i_am_color_9dc">#000009dc</color>
+ <color name="i_am_color_9dd">#000009dd</color>
+ <color name="i_am_color_9de">#000009de</color>
+ <color name="i_am_color_9df">#000009df</color>
+ <color name="i_am_color_9e0">#000009e0</color>
+ <color name="i_am_color_9e1">#000009e1</color>
+ <color name="i_am_color_9e2">#000009e2</color>
+ <color name="i_am_color_9e3">#000009e3</color>
+ <color name="i_am_color_9e4">#000009e4</color>
+ <color name="i_am_color_9e5">#000009e5</color>
+ <color name="i_am_color_9e6">#000009e6</color>
+ <color name="i_am_color_9e7">#000009e7</color>
+ <color name="i_am_color_9e8">#000009e8</color>
+ <color name="i_am_color_9e9">#000009e9</color>
+ <color name="i_am_color_9ea">#000009ea</color>
+ <color name="i_am_color_9eb">#000009eb</color>
+ <color name="i_am_color_9ec">#000009ec</color>
+ <color name="i_am_color_9ed">#000009ed</color>
+ <color name="i_am_color_9ee">#000009ee</color>
+ <color name="i_am_color_9ef">#000009ef</color>
+ <color name="i_am_color_9f0">#000009f0</color>
+ <color name="i_am_color_9f1">#000009f1</color>
+ <color name="i_am_color_9f2">#000009f2</color>
+ <color name="i_am_color_9f3">#000009f3</color>
+ <color name="i_am_color_9f4">#000009f4</color>
+ <color name="i_am_color_9f5">#000009f5</color>
+ <color name="i_am_color_9f6">#000009f6</color>
+ <color name="i_am_color_9f7">#000009f7</color>
+ <color name="i_am_color_9f8">#000009f8</color>
+ <color name="i_am_color_9f9">#000009f9</color>
+ <color name="i_am_color_9fa">#000009fa</color>
+ <color name="i_am_color_9fb">#000009fb</color>
+ <color name="i_am_color_9fc">#000009fc</color>
+ <color name="i_am_color_9fd">#000009fd</color>
+ <color name="i_am_color_9fe">#000009fe</color>
+ <color name="i_am_color_9ff">#000009ff</color>
+ <color name="i_am_color_a00">#00000a00</color>
+ <color name="i_am_color_a01">#00000a01</color>
+ <color name="i_am_color_a02">#00000a02</color>
+ <color name="i_am_color_a03">#00000a03</color>
+ <color name="i_am_color_a04">#00000a04</color>
+ <color name="i_am_color_a05">#00000a05</color>
+ <color name="i_am_color_a06">#00000a06</color>
+ <color name="i_am_color_a07">#00000a07</color>
+ <color name="i_am_color_a08">#00000a08</color>
+ <color name="i_am_color_a09">#00000a09</color>
+ <color name="i_am_color_a0a">#00000a0a</color>
+ <color name="i_am_color_a0b">#00000a0b</color>
+ <color name="i_am_color_a0c">#00000a0c</color>
+ <color name="i_am_color_a0d">#00000a0d</color>
+ <color name="i_am_color_a0e">#00000a0e</color>
+ <color name="i_am_color_a0f">#00000a0f</color>
+ <color name="i_am_color_a10">#00000a10</color>
+ <color name="i_am_color_a11">#00000a11</color>
+ <color name="i_am_color_a12">#00000a12</color>
+ <color name="i_am_color_a13">#00000a13</color>
+ <color name="i_am_color_a14">#00000a14</color>
+ <color name="i_am_color_a15">#00000a15</color>
+ <color name="i_am_color_a16">#00000a16</color>
+ <color name="i_am_color_a17">#00000a17</color>
+ <color name="i_am_color_a18">#00000a18</color>
+ <color name="i_am_color_a19">#00000a19</color>
+ <color name="i_am_color_a1a">#00000a1a</color>
+ <color name="i_am_color_a1b">#00000a1b</color>
+ <color name="i_am_color_a1c">#00000a1c</color>
+ <color name="i_am_color_a1d">#00000a1d</color>
+ <color name="i_am_color_a1e">#00000a1e</color>
+ <color name="i_am_color_a1f">#00000a1f</color>
+ <color name="i_am_color_a20">#00000a20</color>
+ <color name="i_am_color_a21">#00000a21</color>
+ <color name="i_am_color_a22">#00000a22</color>
+ <color name="i_am_color_a23">#00000a23</color>
+ <color name="i_am_color_a24">#00000a24</color>
+ <color name="i_am_color_a25">#00000a25</color>
+ <color name="i_am_color_a26">#00000a26</color>
+ <color name="i_am_color_a27">#00000a27</color>
+ <color name="i_am_color_a28">#00000a28</color>
+ <color name="i_am_color_a29">#00000a29</color>
+ <color name="i_am_color_a2a">#00000a2a</color>
+ <color name="i_am_color_a2b">#00000a2b</color>
+ <color name="i_am_color_a2c">#00000a2c</color>
+ <color name="i_am_color_a2d">#00000a2d</color>
+ <color name="i_am_color_a2e">#00000a2e</color>
+ <color name="i_am_color_a2f">#00000a2f</color>
+ <color name="i_am_color_a30">#00000a30</color>
+ <color name="i_am_color_a31">#00000a31</color>
+ <color name="i_am_color_a32">#00000a32</color>
+ <color name="i_am_color_a33">#00000a33</color>
+ <color name="i_am_color_a34">#00000a34</color>
+ <color name="i_am_color_a35">#00000a35</color>
+ <color name="i_am_color_a36">#00000a36</color>
+ <color name="i_am_color_a37">#00000a37</color>
+ <color name="i_am_color_a38">#00000a38</color>
+ <color name="i_am_color_a39">#00000a39</color>
+ <color name="i_am_color_a3a">#00000a3a</color>
+ <color name="i_am_color_a3b">#00000a3b</color>
+ <color name="i_am_color_a3c">#00000a3c</color>
+ <color name="i_am_color_a3d">#00000a3d</color>
+ <color name="i_am_color_a3e">#00000a3e</color>
+ <color name="i_am_color_a3f">#00000a3f</color>
+ <color name="i_am_color_a40">#00000a40</color>
+ <color name="i_am_color_a41">#00000a41</color>
+ <color name="i_am_color_a42">#00000a42</color>
+ <color name="i_am_color_a43">#00000a43</color>
+ <color name="i_am_color_a44">#00000a44</color>
+ <color name="i_am_color_a45">#00000a45</color>
+ <color name="i_am_color_a46">#00000a46</color>
+ <color name="i_am_color_a47">#00000a47</color>
+ <color name="i_am_color_a48">#00000a48</color>
+ <color name="i_am_color_a49">#00000a49</color>
+ <color name="i_am_color_a4a">#00000a4a</color>
+ <color name="i_am_color_a4b">#00000a4b</color>
+ <color name="i_am_color_a4c">#00000a4c</color>
+ <color name="i_am_color_a4d">#00000a4d</color>
+ <color name="i_am_color_a4e">#00000a4e</color>
+ <color name="i_am_color_a4f">#00000a4f</color>
+ <color name="i_am_color_a50">#00000a50</color>
+ <color name="i_am_color_a51">#00000a51</color>
+ <color name="i_am_color_a52">#00000a52</color>
+ <color name="i_am_color_a53">#00000a53</color>
+ <color name="i_am_color_a54">#00000a54</color>
+ <color name="i_am_color_a55">#00000a55</color>
+ <color name="i_am_color_a56">#00000a56</color>
+ <color name="i_am_color_a57">#00000a57</color>
+ <color name="i_am_color_a58">#00000a58</color>
+ <color name="i_am_color_a59">#00000a59</color>
+ <color name="i_am_color_a5a">#00000a5a</color>
+ <color name="i_am_color_a5b">#00000a5b</color>
+ <color name="i_am_color_a5c">#00000a5c</color>
+ <color name="i_am_color_a5d">#00000a5d</color>
+ <color name="i_am_color_a5e">#00000a5e</color>
+ <color name="i_am_color_a5f">#00000a5f</color>
+ <color name="i_am_color_a60">#00000a60</color>
+ <color name="i_am_color_a61">#00000a61</color>
+ <color name="i_am_color_a62">#00000a62</color>
+ <color name="i_am_color_a63">#00000a63</color>
+ <color name="i_am_color_a64">#00000a64</color>
+ <color name="i_am_color_a65">#00000a65</color>
+ <color name="i_am_color_a66">#00000a66</color>
+ <color name="i_am_color_a67">#00000a67</color>
+ <color name="i_am_color_a68">#00000a68</color>
+ <color name="i_am_color_a69">#00000a69</color>
+ <color name="i_am_color_a6a">#00000a6a</color>
+ <color name="i_am_color_a6b">#00000a6b</color>
+ <color name="i_am_color_a6c">#00000a6c</color>
+ <color name="i_am_color_a6d">#00000a6d</color>
+ <color name="i_am_color_a6e">#00000a6e</color>
+ <color name="i_am_color_a6f">#00000a6f</color>
+ <color name="i_am_color_a70">#00000a70</color>
+ <color name="i_am_color_a71">#00000a71</color>
+ <color name="i_am_color_a72">#00000a72</color>
+ <color name="i_am_color_a73">#00000a73</color>
+ <color name="i_am_color_a74">#00000a74</color>
+ <color name="i_am_color_a75">#00000a75</color>
+ <color name="i_am_color_a76">#00000a76</color>
+ <color name="i_am_color_a77">#00000a77</color>
+ <color name="i_am_color_a78">#00000a78</color>
+ <color name="i_am_color_a79">#00000a79</color>
+ <color name="i_am_color_a7a">#00000a7a</color>
+ <color name="i_am_color_a7b">#00000a7b</color>
+ <color name="i_am_color_a7c">#00000a7c</color>
+ <color name="i_am_color_a7d">#00000a7d</color>
+ <color name="i_am_color_a7e">#00000a7e</color>
+ <color name="i_am_color_a7f">#00000a7f</color>
+ <color name="i_am_color_a80">#00000a80</color>
+ <color name="i_am_color_a81">#00000a81</color>
+ <color name="i_am_color_a82">#00000a82</color>
+ <color name="i_am_color_a83">#00000a83</color>
+ <color name="i_am_color_a84">#00000a84</color>
+ <color name="i_am_color_a85">#00000a85</color>
+ <color name="i_am_color_a86">#00000a86</color>
+ <color name="i_am_color_a87">#00000a87</color>
+ <color name="i_am_color_a88">#00000a88</color>
+ <color name="i_am_color_a89">#00000a89</color>
+ <color name="i_am_color_a8a">#00000a8a</color>
+ <color name="i_am_color_a8b">#00000a8b</color>
+ <color name="i_am_color_a8c">#00000a8c</color>
+ <color name="i_am_color_a8d">#00000a8d</color>
+ <color name="i_am_color_a8e">#00000a8e</color>
+ <color name="i_am_color_a8f">#00000a8f</color>
+ <color name="i_am_color_a90">#00000a90</color>
+ <color name="i_am_color_a91">#00000a91</color>
+ <color name="i_am_color_a92">#00000a92</color>
+ <color name="i_am_color_a93">#00000a93</color>
+ <color name="i_am_color_a94">#00000a94</color>
+ <color name="i_am_color_a95">#00000a95</color>
+ <color name="i_am_color_a96">#00000a96</color>
+ <color name="i_am_color_a97">#00000a97</color>
+ <color name="i_am_color_a98">#00000a98</color>
+ <color name="i_am_color_a99">#00000a99</color>
+ <color name="i_am_color_a9a">#00000a9a</color>
+ <color name="i_am_color_a9b">#00000a9b</color>
+ <color name="i_am_color_a9c">#00000a9c</color>
+ <color name="i_am_color_a9d">#00000a9d</color>
+ <color name="i_am_color_a9e">#00000a9e</color>
+ <color name="i_am_color_a9f">#00000a9f</color>
+ <color name="i_am_color_aa0">#00000aa0</color>
+ <color name="i_am_color_aa1">#00000aa1</color>
+ <color name="i_am_color_aa2">#00000aa2</color>
+ <color name="i_am_color_aa3">#00000aa3</color>
+ <color name="i_am_color_aa4">#00000aa4</color>
+ <color name="i_am_color_aa5">#00000aa5</color>
+ <color name="i_am_color_aa6">#00000aa6</color>
+ <color name="i_am_color_aa7">#00000aa7</color>
+ <color name="i_am_color_aa8">#00000aa8</color>
+ <color name="i_am_color_aa9">#00000aa9</color>
+ <color name="i_am_color_aaa">#00000aaa</color>
+ <color name="i_am_color_aab">#00000aab</color>
+ <color name="i_am_color_aac">#00000aac</color>
+ <color name="i_am_color_aad">#00000aad</color>
+ <color name="i_am_color_aae">#00000aae</color>
+ <color name="i_am_color_aaf">#00000aaf</color>
+ <color name="i_am_color_ab0">#00000ab0</color>
+ <color name="i_am_color_ab1">#00000ab1</color>
+ <color name="i_am_color_ab2">#00000ab2</color>
+ <color name="i_am_color_ab3">#00000ab3</color>
+ <color name="i_am_color_ab4">#00000ab4</color>
+ <color name="i_am_color_ab5">#00000ab5</color>
+ <color name="i_am_color_ab6">#00000ab6</color>
+ <color name="i_am_color_ab7">#00000ab7</color>
+ <color name="i_am_color_ab8">#00000ab8</color>
+ <color name="i_am_color_ab9">#00000ab9</color>
+ <color name="i_am_color_aba">#00000aba</color>
+ <color name="i_am_color_abb">#00000abb</color>
+ <color name="i_am_color_abc">#00000abc</color>
+ <color name="i_am_color_abd">#00000abd</color>
+ <color name="i_am_color_abe">#00000abe</color>
+ <color name="i_am_color_abf">#00000abf</color>
+ <color name="i_am_color_ac0">#00000ac0</color>
+ <color name="i_am_color_ac1">#00000ac1</color>
+ <color name="i_am_color_ac2">#00000ac2</color>
+ <color name="i_am_color_ac3">#00000ac3</color>
+ <color name="i_am_color_ac4">#00000ac4</color>
+ <color name="i_am_color_ac5">#00000ac5</color>
+ <color name="i_am_color_ac6">#00000ac6</color>
+ <color name="i_am_color_ac7">#00000ac7</color>
+ <color name="i_am_color_ac8">#00000ac8</color>
+ <color name="i_am_color_ac9">#00000ac9</color>
+ <color name="i_am_color_aca">#00000aca</color>
+ <color name="i_am_color_acb">#00000acb</color>
+ <color name="i_am_color_acc">#00000acc</color>
+ <color name="i_am_color_acd">#00000acd</color>
+ <color name="i_am_color_ace">#00000ace</color>
+ <color name="i_am_color_acf">#00000acf</color>
+ <color name="i_am_color_ad0">#00000ad0</color>
+ <color name="i_am_color_ad1">#00000ad1</color>
+ <color name="i_am_color_ad2">#00000ad2</color>
+ <color name="i_am_color_ad3">#00000ad3</color>
+ <color name="i_am_color_ad4">#00000ad4</color>
+ <color name="i_am_color_ad5">#00000ad5</color>
+ <color name="i_am_color_ad6">#00000ad6</color>
+ <color name="i_am_color_ad7">#00000ad7</color>
+ <color name="i_am_color_ad8">#00000ad8</color>
+ <color name="i_am_color_ad9">#00000ad9</color>
+ <color name="i_am_color_ada">#00000ada</color>
+ <color name="i_am_color_adb">#00000adb</color>
+ <color name="i_am_color_adc">#00000adc</color>
+ <color name="i_am_color_add">#00000add</color>
+ <color name="i_am_color_ade">#00000ade</color>
+ <color name="i_am_color_adf">#00000adf</color>
+ <color name="i_am_color_ae0">#00000ae0</color>
+ <color name="i_am_color_ae1">#00000ae1</color>
+ <color name="i_am_color_ae2">#00000ae2</color>
+ <color name="i_am_color_ae3">#00000ae3</color>
+ <color name="i_am_color_ae4">#00000ae4</color>
+ <color name="i_am_color_ae5">#00000ae5</color>
+ <color name="i_am_color_ae6">#00000ae6</color>
+ <color name="i_am_color_ae7">#00000ae7</color>
+ <color name="i_am_color_ae8">#00000ae8</color>
+ <color name="i_am_color_ae9">#00000ae9</color>
+ <color name="i_am_color_aea">#00000aea</color>
+ <color name="i_am_color_aeb">#00000aeb</color>
+ <color name="i_am_color_aec">#00000aec</color>
+ <color name="i_am_color_aed">#00000aed</color>
+ <color name="i_am_color_aee">#00000aee</color>
+ <color name="i_am_color_aef">#00000aef</color>
+ <color name="i_am_color_af0">#00000af0</color>
+ <color name="i_am_color_af1">#00000af1</color>
+ <color name="i_am_color_af2">#00000af2</color>
+ <color name="i_am_color_af3">#00000af3</color>
+ <color name="i_am_color_af4">#00000af4</color>
+ <color name="i_am_color_af5">#00000af5</color>
+ <color name="i_am_color_af6">#00000af6</color>
+ <color name="i_am_color_af7">#00000af7</color>
+ <color name="i_am_color_af8">#00000af8</color>
+ <color name="i_am_color_af9">#00000af9</color>
+ <color name="i_am_color_afa">#00000afa</color>
+ <color name="i_am_color_afb">#00000afb</color>
+ <color name="i_am_color_afc">#00000afc</color>
+ <color name="i_am_color_afd">#00000afd</color>
+ <color name="i_am_color_afe">#00000afe</color>
+ <color name="i_am_color_aff">#00000aff</color>
+ <color name="i_am_color_b00">#00000b00</color>
+ <color name="i_am_color_b01">#00000b01</color>
+ <color name="i_am_color_b02">#00000b02</color>
+ <color name="i_am_color_b03">#00000b03</color>
+ <color name="i_am_color_b04">#00000b04</color>
+ <color name="i_am_color_b05">#00000b05</color>
+ <color name="i_am_color_b06">#00000b06</color>
+ <color name="i_am_color_b07">#00000b07</color>
+ <color name="i_am_color_b08">#00000b08</color>
+ <color name="i_am_color_b09">#00000b09</color>
+ <color name="i_am_color_b0a">#00000b0a</color>
+ <color name="i_am_color_b0b">#00000b0b</color>
+ <color name="i_am_color_b0c">#00000b0c</color>
+ <color name="i_am_color_b0d">#00000b0d</color>
+ <color name="i_am_color_b0e">#00000b0e</color>
+ <color name="i_am_color_b0f">#00000b0f</color>
+ <color name="i_am_color_b10">#00000b10</color>
+ <color name="i_am_color_b11">#00000b11</color>
+ <color name="i_am_color_b12">#00000b12</color>
+ <color name="i_am_color_b13">#00000b13</color>
+ <color name="i_am_color_b14">#00000b14</color>
+ <color name="i_am_color_b15">#00000b15</color>
+ <color name="i_am_color_b16">#00000b16</color>
+ <color name="i_am_color_b17">#00000b17</color>
+ <color name="i_am_color_b18">#00000b18</color>
+ <color name="i_am_color_b19">#00000b19</color>
+ <color name="i_am_color_b1a">#00000b1a</color>
+ <color name="i_am_color_b1b">#00000b1b</color>
+ <color name="i_am_color_b1c">#00000b1c</color>
+ <color name="i_am_color_b1d">#00000b1d</color>
+ <color name="i_am_color_b1e">#00000b1e</color>
+ <color name="i_am_color_b1f">#00000b1f</color>
+ <color name="i_am_color_b20">#00000b20</color>
+ <color name="i_am_color_b21">#00000b21</color>
+ <color name="i_am_color_b22">#00000b22</color>
+ <color name="i_am_color_b23">#00000b23</color>
+ <color name="i_am_color_b24">#00000b24</color>
+ <color name="i_am_color_b25">#00000b25</color>
+ <color name="i_am_color_b26">#00000b26</color>
+ <color name="i_am_color_b27">#00000b27</color>
+ <color name="i_am_color_b28">#00000b28</color>
+ <color name="i_am_color_b29">#00000b29</color>
+ <color name="i_am_color_b2a">#00000b2a</color>
+ <color name="i_am_color_b2b">#00000b2b</color>
+ <color name="i_am_color_b2c">#00000b2c</color>
+ <color name="i_am_color_b2d">#00000b2d</color>
+ <color name="i_am_color_b2e">#00000b2e</color>
+ <color name="i_am_color_b2f">#00000b2f</color>
+ <color name="i_am_color_b30">#00000b30</color>
+ <color name="i_am_color_b31">#00000b31</color>
+ <color name="i_am_color_b32">#00000b32</color>
+ <color name="i_am_color_b33">#00000b33</color>
+ <color name="i_am_color_b34">#00000b34</color>
+ <color name="i_am_color_b35">#00000b35</color>
+ <color name="i_am_color_b36">#00000b36</color>
+ <color name="i_am_color_b37">#00000b37</color>
+ <color name="i_am_color_b38">#00000b38</color>
+ <color name="i_am_color_b39">#00000b39</color>
+ <color name="i_am_color_b3a">#00000b3a</color>
+ <color name="i_am_color_b3b">#00000b3b</color>
+ <color name="i_am_color_b3c">#00000b3c</color>
+ <color name="i_am_color_b3d">#00000b3d</color>
+ <color name="i_am_color_b3e">#00000b3e</color>
+ <color name="i_am_color_b3f">#00000b3f</color>
+ <color name="i_am_color_b40">#00000b40</color>
+ <color name="i_am_color_b41">#00000b41</color>
+ <color name="i_am_color_b42">#00000b42</color>
+ <color name="i_am_color_b43">#00000b43</color>
+ <color name="i_am_color_b44">#00000b44</color>
+ <color name="i_am_color_b45">#00000b45</color>
+ <color name="i_am_color_b46">#00000b46</color>
+ <color name="i_am_color_b47">#00000b47</color>
+ <color name="i_am_color_b48">#00000b48</color>
+ <color name="i_am_color_b49">#00000b49</color>
+ <color name="i_am_color_b4a">#00000b4a</color>
+ <color name="i_am_color_b4b">#00000b4b</color>
+ <color name="i_am_color_b4c">#00000b4c</color>
+ <color name="i_am_color_b4d">#00000b4d</color>
+ <color name="i_am_color_b4e">#00000b4e</color>
+ <color name="i_am_color_b4f">#00000b4f</color>
+ <color name="i_am_color_b50">#00000b50</color>
+ <color name="i_am_color_b51">#00000b51</color>
+ <color name="i_am_color_b52">#00000b52</color>
+ <color name="i_am_color_b53">#00000b53</color>
+ <color name="i_am_color_b54">#00000b54</color>
+ <color name="i_am_color_b55">#00000b55</color>
+ <color name="i_am_color_b56">#00000b56</color>
+ <color name="i_am_color_b57">#00000b57</color>
+ <color name="i_am_color_b58">#00000b58</color>
+ <color name="i_am_color_b59">#00000b59</color>
+ <color name="i_am_color_b5a">#00000b5a</color>
+ <color name="i_am_color_b5b">#00000b5b</color>
+ <color name="i_am_color_b5c">#00000b5c</color>
+ <color name="i_am_color_b5d">#00000b5d</color>
+ <color name="i_am_color_b5e">#00000b5e</color>
+ <color name="i_am_color_b5f">#00000b5f</color>
+ <color name="i_am_color_b60">#00000b60</color>
+ <color name="i_am_color_b61">#00000b61</color>
+ <color name="i_am_color_b62">#00000b62</color>
+ <color name="i_am_color_b63">#00000b63</color>
+ <color name="i_am_color_b64">#00000b64</color>
+ <color name="i_am_color_b65">#00000b65</color>
+ <color name="i_am_color_b66">#00000b66</color>
+ <color name="i_am_color_b67">#00000b67</color>
+ <color name="i_am_color_b68">#00000b68</color>
+ <color name="i_am_color_b69">#00000b69</color>
+ <color name="i_am_color_b6a">#00000b6a</color>
+ <color name="i_am_color_b6b">#00000b6b</color>
+ <color name="i_am_color_b6c">#00000b6c</color>
+ <color name="i_am_color_b6d">#00000b6d</color>
+ <color name="i_am_color_b6e">#00000b6e</color>
+ <color name="i_am_color_b6f">#00000b6f</color>
+ <color name="i_am_color_b70">#00000b70</color>
+ <color name="i_am_color_b71">#00000b71</color>
+ <color name="i_am_color_b72">#00000b72</color>
+ <color name="i_am_color_b73">#00000b73</color>
+ <color name="i_am_color_b74">#00000b74</color>
+ <color name="i_am_color_b75">#00000b75</color>
+ <color name="i_am_color_b76">#00000b76</color>
+ <color name="i_am_color_b77">#00000b77</color>
+ <color name="i_am_color_b78">#00000b78</color>
+ <color name="i_am_color_b79">#00000b79</color>
+ <color name="i_am_color_b7a">#00000b7a</color>
+ <color name="i_am_color_b7b">#00000b7b</color>
+ <color name="i_am_color_b7c">#00000b7c</color>
+ <color name="i_am_color_b7d">#00000b7d</color>
+ <color name="i_am_color_b7e">#00000b7e</color>
+ <color name="i_am_color_b7f">#00000b7f</color>
+ <color name="i_am_color_b80">#00000b80</color>
+ <color name="i_am_color_b81">#00000b81</color>
+ <color name="i_am_color_b82">#00000b82</color>
+ <color name="i_am_color_b83">#00000b83</color>
+ <color name="i_am_color_b84">#00000b84</color>
+ <color name="i_am_color_b85">#00000b85</color>
+ <color name="i_am_color_b86">#00000b86</color>
+ <color name="i_am_color_b87">#00000b87</color>
+ <color name="i_am_color_b88">#00000b88</color>
+ <color name="i_am_color_b89">#00000b89</color>
+ <color name="i_am_color_b8a">#00000b8a</color>
+ <color name="i_am_color_b8b">#00000b8b</color>
+ <color name="i_am_color_b8c">#00000b8c</color>
+ <color name="i_am_color_b8d">#00000b8d</color>
+ <color name="i_am_color_b8e">#00000b8e</color>
+ <color name="i_am_color_b8f">#00000b8f</color>
+ <color name="i_am_color_b90">#00000b90</color>
+ <color name="i_am_color_b91">#00000b91</color>
+ <color name="i_am_color_b92">#00000b92</color>
+ <color name="i_am_color_b93">#00000b93</color>
+ <color name="i_am_color_b94">#00000b94</color>
+ <color name="i_am_color_b95">#00000b95</color>
+ <color name="i_am_color_b96">#00000b96</color>
+ <color name="i_am_color_b97">#00000b97</color>
+ <color name="i_am_color_b98">#00000b98</color>
+ <color name="i_am_color_b99">#00000b99</color>
+ <color name="i_am_color_b9a">#00000b9a</color>
+ <color name="i_am_color_b9b">#00000b9b</color>
+ <color name="i_am_color_b9c">#00000b9c</color>
+ <color name="i_am_color_b9d">#00000b9d</color>
+ <color name="i_am_color_b9e">#00000b9e</color>
+ <color name="i_am_color_b9f">#00000b9f</color>
+ <color name="i_am_color_ba0">#00000ba0</color>
+ <color name="i_am_color_ba1">#00000ba1</color>
+ <color name="i_am_color_ba2">#00000ba2</color>
+ <color name="i_am_color_ba3">#00000ba3</color>
+ <color name="i_am_color_ba4">#00000ba4</color>
+ <color name="i_am_color_ba5">#00000ba5</color>
+ <color name="i_am_color_ba6">#00000ba6</color>
+ <color name="i_am_color_ba7">#00000ba7</color>
+ <color name="i_am_color_ba8">#00000ba8</color>
+ <color name="i_am_color_ba9">#00000ba9</color>
+ <color name="i_am_color_baa">#00000baa</color>
+ <color name="i_am_color_bab">#00000bab</color>
+ <color name="i_am_color_bac">#00000bac</color>
+ <color name="i_am_color_bad">#00000bad</color>
+ <color name="i_am_color_bae">#00000bae</color>
+ <color name="i_am_color_baf">#00000baf</color>
+ <color name="i_am_color_bb0">#00000bb0</color>
+ <color name="i_am_color_bb1">#00000bb1</color>
+ <color name="i_am_color_bb2">#00000bb2</color>
+ <color name="i_am_color_bb3">#00000bb3</color>
+ <color name="i_am_color_bb4">#00000bb4</color>
+ <color name="i_am_color_bb5">#00000bb5</color>
+ <color name="i_am_color_bb6">#00000bb6</color>
+ <color name="i_am_color_bb7">#00000bb7</color>
+ <color name="i_am_color_bb8">#00000bb8</color>
+ <color name="i_am_color_bb9">#00000bb9</color>
+ <color name="i_am_color_bba">#00000bba</color>
+ <color name="i_am_color_bbb">#00000bbb</color>
+ <color name="i_am_color_bbc">#00000bbc</color>
+ <color name="i_am_color_bbd">#00000bbd</color>
+ <color name="i_am_color_bbe">#00000bbe</color>
+ <color name="i_am_color_bbf">#00000bbf</color>
+ <color name="i_am_color_bc0">#00000bc0</color>
+ <color name="i_am_color_bc1">#00000bc1</color>
+ <color name="i_am_color_bc2">#00000bc2</color>
+ <color name="i_am_color_bc3">#00000bc3</color>
+ <color name="i_am_color_bc4">#00000bc4</color>
+ <color name="i_am_color_bc5">#00000bc5</color>
+ <color name="i_am_color_bc6">#00000bc6</color>
+ <color name="i_am_color_bc7">#00000bc7</color>
+ <color name="i_am_color_bc8">#00000bc8</color>
+ <color name="i_am_color_bc9">#00000bc9</color>
+ <color name="i_am_color_bca">#00000bca</color>
+ <color name="i_am_color_bcb">#00000bcb</color>
+ <color name="i_am_color_bcc">#00000bcc</color>
+ <color name="i_am_color_bcd">#00000bcd</color>
+ <color name="i_am_color_bce">#00000bce</color>
+ <color name="i_am_color_bcf">#00000bcf</color>
+ <color name="i_am_color_bd0">#00000bd0</color>
+ <color name="i_am_color_bd1">#00000bd1</color>
+ <color name="i_am_color_bd2">#00000bd2</color>
+ <color name="i_am_color_bd3">#00000bd3</color>
+ <color name="i_am_color_bd4">#00000bd4</color>
+ <color name="i_am_color_bd5">#00000bd5</color>
+ <color name="i_am_color_bd6">#00000bd6</color>
+ <color name="i_am_color_bd7">#00000bd7</color>
+ <color name="i_am_color_bd8">#00000bd8</color>
+ <color name="i_am_color_bd9">#00000bd9</color>
+ <color name="i_am_color_bda">#00000bda</color>
+ <color name="i_am_color_bdb">#00000bdb</color>
+ <color name="i_am_color_bdc">#00000bdc</color>
+ <color name="i_am_color_bdd">#00000bdd</color>
+ <color name="i_am_color_bde">#00000bde</color>
+ <color name="i_am_color_bdf">#00000bdf</color>
+ <color name="i_am_color_be0">#00000be0</color>
+ <color name="i_am_color_be1">#00000be1</color>
+ <color name="i_am_color_be2">#00000be2</color>
+ <color name="i_am_color_be3">#00000be3</color>
+ <color name="i_am_color_be4">#00000be4</color>
+ <color name="i_am_color_be5">#00000be5</color>
+ <color name="i_am_color_be6">#00000be6</color>
+ <color name="i_am_color_be7">#00000be7</color>
+ <color name="i_am_color_be8">#00000be8</color>
+ <color name="i_am_color_be9">#00000be9</color>
+ <color name="i_am_color_bea">#00000bea</color>
+ <color name="i_am_color_beb">#00000beb</color>
+ <color name="i_am_color_bec">#00000bec</color>
+ <color name="i_am_color_bed">#00000bed</color>
+ <color name="i_am_color_bee">#00000bee</color>
+ <color name="i_am_color_bef">#00000bef</color>
+ <color name="i_am_color_bf0">#00000bf0</color>
+ <color name="i_am_color_bf1">#00000bf1</color>
+ <color name="i_am_color_bf2">#00000bf2</color>
+ <color name="i_am_color_bf3">#00000bf3</color>
+ <color name="i_am_color_bf4">#00000bf4</color>
+ <color name="i_am_color_bf5">#00000bf5</color>
+ <color name="i_am_color_bf6">#00000bf6</color>
+ <color name="i_am_color_bf7">#00000bf7</color>
+ <color name="i_am_color_bf8">#00000bf8</color>
+ <color name="i_am_color_bf9">#00000bf9</color>
+ <color name="i_am_color_bfa">#00000bfa</color>
+ <color name="i_am_color_bfb">#00000bfb</color>
+ <color name="i_am_color_bfc">#00000bfc</color>
+ <color name="i_am_color_bfd">#00000bfd</color>
+ <color name="i_am_color_bfe">#00000bfe</color>
+ <color name="i_am_color_bff">#00000bff</color>
+ <color name="i_am_color_c00">#00000c00</color>
+ <color name="i_am_color_c01">#00000c01</color>
+ <color name="i_am_color_c02">#00000c02</color>
+ <color name="i_am_color_c03">#00000c03</color>
+ <color name="i_am_color_c04">#00000c04</color>
+ <color name="i_am_color_c05">#00000c05</color>
+ <color name="i_am_color_c06">#00000c06</color>
+ <color name="i_am_color_c07">#00000c07</color>
+ <color name="i_am_color_c08">#00000c08</color>
+ <color name="i_am_color_c09">#00000c09</color>
+ <color name="i_am_color_c0a">#00000c0a</color>
+ <color name="i_am_color_c0b">#00000c0b</color>
+ <color name="i_am_color_c0c">#00000c0c</color>
+ <color name="i_am_color_c0d">#00000c0d</color>
+ <color name="i_am_color_c0e">#00000c0e</color>
+ <color name="i_am_color_c0f">#00000c0f</color>
+ <color name="i_am_color_c10">#00000c10</color>
+ <color name="i_am_color_c11">#00000c11</color>
+ <color name="i_am_color_c12">#00000c12</color>
+ <color name="i_am_color_c13">#00000c13</color>
+ <color name="i_am_color_c14">#00000c14</color>
+ <color name="i_am_color_c15">#00000c15</color>
+ <color name="i_am_color_c16">#00000c16</color>
+ <color name="i_am_color_c17">#00000c17</color>
+ <color name="i_am_color_c18">#00000c18</color>
+ <color name="i_am_color_c19">#00000c19</color>
+ <color name="i_am_color_c1a">#00000c1a</color>
+ <color name="i_am_color_c1b">#00000c1b</color>
+ <color name="i_am_color_c1c">#00000c1c</color>
+ <color name="i_am_color_c1d">#00000c1d</color>
+ <color name="i_am_color_c1e">#00000c1e</color>
+ <color name="i_am_color_c1f">#00000c1f</color>
+ <color name="i_am_color_c20">#00000c20</color>
+ <color name="i_am_color_c21">#00000c21</color>
+ <color name="i_am_color_c22">#00000c22</color>
+ <color name="i_am_color_c23">#00000c23</color>
+ <color name="i_am_color_c24">#00000c24</color>
+ <color name="i_am_color_c25">#00000c25</color>
+ <color name="i_am_color_c26">#00000c26</color>
+ <color name="i_am_color_c27">#00000c27</color>
+ <color name="i_am_color_c28">#00000c28</color>
+ <color name="i_am_color_c29">#00000c29</color>
+ <color name="i_am_color_c2a">#00000c2a</color>
+ <color name="i_am_color_c2b">#00000c2b</color>
+ <color name="i_am_color_c2c">#00000c2c</color>
+ <color name="i_am_color_c2d">#00000c2d</color>
+ <color name="i_am_color_c2e">#00000c2e</color>
+ <color name="i_am_color_c2f">#00000c2f</color>
+ <color name="i_am_color_c30">#00000c30</color>
+ <color name="i_am_color_c31">#00000c31</color>
+ <color name="i_am_color_c32">#00000c32</color>
+ <color name="i_am_color_c33">#00000c33</color>
+ <color name="i_am_color_c34">#00000c34</color>
+ <color name="i_am_color_c35">#00000c35</color>
+ <color name="i_am_color_c36">#00000c36</color>
+ <color name="i_am_color_c37">#00000c37</color>
+ <color name="i_am_color_c38">#00000c38</color>
+ <color name="i_am_color_c39">#00000c39</color>
+ <color name="i_am_color_c3a">#00000c3a</color>
+ <color name="i_am_color_c3b">#00000c3b</color>
+ <color name="i_am_color_c3c">#00000c3c</color>
+ <color name="i_am_color_c3d">#00000c3d</color>
+ <color name="i_am_color_c3e">#00000c3e</color>
+ <color name="i_am_color_c3f">#00000c3f</color>
+ <color name="i_am_color_c40">#00000c40</color>
+ <color name="i_am_color_c41">#00000c41</color>
+ <color name="i_am_color_c42">#00000c42</color>
+ <color name="i_am_color_c43">#00000c43</color>
+ <color name="i_am_color_c44">#00000c44</color>
+ <color name="i_am_color_c45">#00000c45</color>
+ <color name="i_am_color_c46">#00000c46</color>
+ <color name="i_am_color_c47">#00000c47</color>
+ <color name="i_am_color_c48">#00000c48</color>
+ <color name="i_am_color_c49">#00000c49</color>
+ <color name="i_am_color_c4a">#00000c4a</color>
+ <color name="i_am_color_c4b">#00000c4b</color>
+ <color name="i_am_color_c4c">#00000c4c</color>
+ <color name="i_am_color_c4d">#00000c4d</color>
+ <color name="i_am_color_c4e">#00000c4e</color>
+ <color name="i_am_color_c4f">#00000c4f</color>
+ <color name="i_am_color_c50">#00000c50</color>
+ <color name="i_am_color_c51">#00000c51</color>
+ <color name="i_am_color_c52">#00000c52</color>
+ <color name="i_am_color_c53">#00000c53</color>
+ <color name="i_am_color_c54">#00000c54</color>
+ <color name="i_am_color_c55">#00000c55</color>
+ <color name="i_am_color_c56">#00000c56</color>
+ <color name="i_am_color_c57">#00000c57</color>
+ <color name="i_am_color_c58">#00000c58</color>
+ <color name="i_am_color_c59">#00000c59</color>
+ <color name="i_am_color_c5a">#00000c5a</color>
+ <color name="i_am_color_c5b">#00000c5b</color>
+ <color name="i_am_color_c5c">#00000c5c</color>
+ <color name="i_am_color_c5d">#00000c5d</color>
+ <color name="i_am_color_c5e">#00000c5e</color>
+ <color name="i_am_color_c5f">#00000c5f</color>
+ <color name="i_am_color_c60">#00000c60</color>
+ <color name="i_am_color_c61">#00000c61</color>
+ <color name="i_am_color_c62">#00000c62</color>
+ <color name="i_am_color_c63">#00000c63</color>
+ <color name="i_am_color_c64">#00000c64</color>
+ <color name="i_am_color_c65">#00000c65</color>
+ <color name="i_am_color_c66">#00000c66</color>
+ <color name="i_am_color_c67">#00000c67</color>
+ <color name="i_am_color_c68">#00000c68</color>
+ <color name="i_am_color_c69">#00000c69</color>
+ <color name="i_am_color_c6a">#00000c6a</color>
+ <color name="i_am_color_c6b">#00000c6b</color>
+ <color name="i_am_color_c6c">#00000c6c</color>
+ <color name="i_am_color_c6d">#00000c6d</color>
+ <color name="i_am_color_c6e">#00000c6e</color>
+ <color name="i_am_color_c6f">#00000c6f</color>
+ <color name="i_am_color_c70">#00000c70</color>
+ <color name="i_am_color_c71">#00000c71</color>
+ <color name="i_am_color_c72">#00000c72</color>
+ <color name="i_am_color_c73">#00000c73</color>
+ <color name="i_am_color_c74">#00000c74</color>
+ <color name="i_am_color_c75">#00000c75</color>
+ <color name="i_am_color_c76">#00000c76</color>
+ <color name="i_am_color_c77">#00000c77</color>
+ <color name="i_am_color_c78">#00000c78</color>
+ <color name="i_am_color_c79">#00000c79</color>
+ <color name="i_am_color_c7a">#00000c7a</color>
+ <color name="i_am_color_c7b">#00000c7b</color>
+ <color name="i_am_color_c7c">#00000c7c</color>
+ <color name="i_am_color_c7d">#00000c7d</color>
+ <color name="i_am_color_c7e">#00000c7e</color>
+ <color name="i_am_color_c7f">#00000c7f</color>
+ <color name="i_am_color_c80">#00000c80</color>
+ <color name="i_am_color_c81">#00000c81</color>
+ <color name="i_am_color_c82">#00000c82</color>
+ <color name="i_am_color_c83">#00000c83</color>
+ <color name="i_am_color_c84">#00000c84</color>
+ <color name="i_am_color_c85">#00000c85</color>
+ <color name="i_am_color_c86">#00000c86</color>
+ <color name="i_am_color_c87">#00000c87</color>
+ <color name="i_am_color_c88">#00000c88</color>
+ <color name="i_am_color_c89">#00000c89</color>
+ <color name="i_am_color_c8a">#00000c8a</color>
+ <color name="i_am_color_c8b">#00000c8b</color>
+ <color name="i_am_color_c8c">#00000c8c</color>
+ <color name="i_am_color_c8d">#00000c8d</color>
+ <color name="i_am_color_c8e">#00000c8e</color>
+ <color name="i_am_color_c8f">#00000c8f</color>
+ <color name="i_am_color_c90">#00000c90</color>
+ <color name="i_am_color_c91">#00000c91</color>
+ <color name="i_am_color_c92">#00000c92</color>
+ <color name="i_am_color_c93">#00000c93</color>
+ <color name="i_am_color_c94">#00000c94</color>
+ <color name="i_am_color_c95">#00000c95</color>
+ <color name="i_am_color_c96">#00000c96</color>
+ <color name="i_am_color_c97">#00000c97</color>
+ <color name="i_am_color_c98">#00000c98</color>
+ <color name="i_am_color_c99">#00000c99</color>
+ <color name="i_am_color_c9a">#00000c9a</color>
+ <color name="i_am_color_c9b">#00000c9b</color>
+ <color name="i_am_color_c9c">#00000c9c</color>
+ <color name="i_am_color_c9d">#00000c9d</color>
+ <color name="i_am_color_c9e">#00000c9e</color>
+ <color name="i_am_color_c9f">#00000c9f</color>
+ <color name="i_am_color_ca0">#00000ca0</color>
+ <color name="i_am_color_ca1">#00000ca1</color>
+ <color name="i_am_color_ca2">#00000ca2</color>
+ <color name="i_am_color_ca3">#00000ca3</color>
+ <color name="i_am_color_ca4">#00000ca4</color>
+ <color name="i_am_color_ca5">#00000ca5</color>
+ <color name="i_am_color_ca6">#00000ca6</color>
+ <color name="i_am_color_ca7">#00000ca7</color>
+ <color name="i_am_color_ca8">#00000ca8</color>
+ <color name="i_am_color_ca9">#00000ca9</color>
+ <color name="i_am_color_caa">#00000caa</color>
+ <color name="i_am_color_cab">#00000cab</color>
+ <color name="i_am_color_cac">#00000cac</color>
+ <color name="i_am_color_cad">#00000cad</color>
+ <color name="i_am_color_cae">#00000cae</color>
+ <color name="i_am_color_caf">#00000caf</color>
+ <color name="i_am_color_cb0">#00000cb0</color>
+ <color name="i_am_color_cb1">#00000cb1</color>
+ <color name="i_am_color_cb2">#00000cb2</color>
+ <color name="i_am_color_cb3">#00000cb3</color>
+ <color name="i_am_color_cb4">#00000cb4</color>
+ <color name="i_am_color_cb5">#00000cb5</color>
+ <color name="i_am_color_cb6">#00000cb6</color>
+ <color name="i_am_color_cb7">#00000cb7</color>
+ <color name="i_am_color_cb8">#00000cb8</color>
+ <color name="i_am_color_cb9">#00000cb9</color>
+ <color name="i_am_color_cba">#00000cba</color>
+ <color name="i_am_color_cbb">#00000cbb</color>
+ <color name="i_am_color_cbc">#00000cbc</color>
+ <color name="i_am_color_cbd">#00000cbd</color>
+ <color name="i_am_color_cbe">#00000cbe</color>
+ <color name="i_am_color_cbf">#00000cbf</color>
+ <color name="i_am_color_cc0">#00000cc0</color>
+ <color name="i_am_color_cc1">#00000cc1</color>
+ <color name="i_am_color_cc2">#00000cc2</color>
+ <color name="i_am_color_cc3">#00000cc3</color>
+ <color name="i_am_color_cc4">#00000cc4</color>
+ <color name="i_am_color_cc5">#00000cc5</color>
+ <color name="i_am_color_cc6">#00000cc6</color>
+ <color name="i_am_color_cc7">#00000cc7</color>
+ <color name="i_am_color_cc8">#00000cc8</color>
+ <color name="i_am_color_cc9">#00000cc9</color>
+ <color name="i_am_color_cca">#00000cca</color>
+ <color name="i_am_color_ccb">#00000ccb</color>
+ <color name="i_am_color_ccc">#00000ccc</color>
+ <color name="i_am_color_ccd">#00000ccd</color>
+ <color name="i_am_color_cce">#00000cce</color>
+ <color name="i_am_color_ccf">#00000ccf</color>
+ <color name="i_am_color_cd0">#00000cd0</color>
+ <color name="i_am_color_cd1">#00000cd1</color>
+ <color name="i_am_color_cd2">#00000cd2</color>
+ <color name="i_am_color_cd3">#00000cd3</color>
+ <color name="i_am_color_cd4">#00000cd4</color>
+ <color name="i_am_color_cd5">#00000cd5</color>
+ <color name="i_am_color_cd6">#00000cd6</color>
+ <color name="i_am_color_cd7">#00000cd7</color>
+ <color name="i_am_color_cd8">#00000cd8</color>
+ <color name="i_am_color_cd9">#00000cd9</color>
+ <color name="i_am_color_cda">#00000cda</color>
+ <color name="i_am_color_cdb">#00000cdb</color>
+ <color name="i_am_color_cdc">#00000cdc</color>
+ <color name="i_am_color_cdd">#00000cdd</color>
+ <color name="i_am_color_cde">#00000cde</color>
+ <color name="i_am_color_cdf">#00000cdf</color>
+ <color name="i_am_color_ce0">#00000ce0</color>
+ <color name="i_am_color_ce1">#00000ce1</color>
+ <color name="i_am_color_ce2">#00000ce2</color>
+ <color name="i_am_color_ce3">#00000ce3</color>
+ <color name="i_am_color_ce4">#00000ce4</color>
+ <color name="i_am_color_ce5">#00000ce5</color>
+ <color name="i_am_color_ce6">#00000ce6</color>
+ <color name="i_am_color_ce7">#00000ce7</color>
+ <color name="i_am_color_ce8">#00000ce8</color>
+ <color name="i_am_color_ce9">#00000ce9</color>
+ <color name="i_am_color_cea">#00000cea</color>
+ <color name="i_am_color_ceb">#00000ceb</color>
+ <color name="i_am_color_cec">#00000cec</color>
+ <color name="i_am_color_ced">#00000ced</color>
+ <color name="i_am_color_cee">#00000cee</color>
+ <color name="i_am_color_cef">#00000cef</color>
+ <color name="i_am_color_cf0">#00000cf0</color>
+ <color name="i_am_color_cf1">#00000cf1</color>
+ <color name="i_am_color_cf2">#00000cf2</color>
+ <color name="i_am_color_cf3">#00000cf3</color>
+ <color name="i_am_color_cf4">#00000cf4</color>
+ <color name="i_am_color_cf5">#00000cf5</color>
+ <color name="i_am_color_cf6">#00000cf6</color>
+ <color name="i_am_color_cf7">#00000cf7</color>
+ <color name="i_am_color_cf8">#00000cf8</color>
+ <color name="i_am_color_cf9">#00000cf9</color>
+ <color name="i_am_color_cfa">#00000cfa</color>
+ <color name="i_am_color_cfb">#00000cfb</color>
+ <color name="i_am_color_cfc">#00000cfc</color>
+ <color name="i_am_color_cfd">#00000cfd</color>
+ <color name="i_am_color_cfe">#00000cfe</color>
+ <color name="i_am_color_cff">#00000cff</color>
+ <color name="i_am_color_d00">#00000d00</color>
+ <color name="i_am_color_d01">#00000d01</color>
+ <color name="i_am_color_d02">#00000d02</color>
+ <color name="i_am_color_d03">#00000d03</color>
+ <color name="i_am_color_d04">#00000d04</color>
+ <color name="i_am_color_d05">#00000d05</color>
+ <color name="i_am_color_d06">#00000d06</color>
+ <color name="i_am_color_d07">#00000d07</color>
+ <color name="i_am_color_d08">#00000d08</color>
+ <color name="i_am_color_d09">#00000d09</color>
+ <color name="i_am_color_d0a">#00000d0a</color>
+ <color name="i_am_color_d0b">#00000d0b</color>
+ <color name="i_am_color_d0c">#00000d0c</color>
+ <color name="i_am_color_d0d">#00000d0d</color>
+ <color name="i_am_color_d0e">#00000d0e</color>
+ <color name="i_am_color_d0f">#00000d0f</color>
+ <color name="i_am_color_d10">#00000d10</color>
+ <color name="i_am_color_d11">#00000d11</color>
+ <color name="i_am_color_d12">#00000d12</color>
+ <color name="i_am_color_d13">#00000d13</color>
+ <color name="i_am_color_d14">#00000d14</color>
+ <color name="i_am_color_d15">#00000d15</color>
+ <color name="i_am_color_d16">#00000d16</color>
+ <color name="i_am_color_d17">#00000d17</color>
+ <color name="i_am_color_d18">#00000d18</color>
+ <color name="i_am_color_d19">#00000d19</color>
+ <color name="i_am_color_d1a">#00000d1a</color>
+ <color name="i_am_color_d1b">#00000d1b</color>
+ <color name="i_am_color_d1c">#00000d1c</color>
+ <color name="i_am_color_d1d">#00000d1d</color>
+ <color name="i_am_color_d1e">#00000d1e</color>
+ <color name="i_am_color_d1f">#00000d1f</color>
+ <color name="i_am_color_d20">#00000d20</color>
+ <color name="i_am_color_d21">#00000d21</color>
+ <color name="i_am_color_d22">#00000d22</color>
+ <color name="i_am_color_d23">#00000d23</color>
+ <color name="i_am_color_d24">#00000d24</color>
+ <color name="i_am_color_d25">#00000d25</color>
+ <color name="i_am_color_d26">#00000d26</color>
+ <color name="i_am_color_d27">#00000d27</color>
+ <color name="i_am_color_d28">#00000d28</color>
+ <color name="i_am_color_d29">#00000d29</color>
+ <color name="i_am_color_d2a">#00000d2a</color>
+ <color name="i_am_color_d2b">#00000d2b</color>
+ <color name="i_am_color_d2c">#00000d2c</color>
+ <color name="i_am_color_d2d">#00000d2d</color>
+ <color name="i_am_color_d2e">#00000d2e</color>
+ <color name="i_am_color_d2f">#00000d2f</color>
+ <color name="i_am_color_d30">#00000d30</color>
+ <color name="i_am_color_d31">#00000d31</color>
+ <color name="i_am_color_d32">#00000d32</color>
+ <color name="i_am_color_d33">#00000d33</color>
+ <color name="i_am_color_d34">#00000d34</color>
+ <color name="i_am_color_d35">#00000d35</color>
+ <color name="i_am_color_d36">#00000d36</color>
+ <color name="i_am_color_d37">#00000d37</color>
+ <color name="i_am_color_d38">#00000d38</color>
+ <color name="i_am_color_d39">#00000d39</color>
+ <color name="i_am_color_d3a">#00000d3a</color>
+ <color name="i_am_color_d3b">#00000d3b</color>
+ <color name="i_am_color_d3c">#00000d3c</color>
+ <color name="i_am_color_d3d">#00000d3d</color>
+ <color name="i_am_color_d3e">#00000d3e</color>
+ <color name="i_am_color_d3f">#00000d3f</color>
+ <color name="i_am_color_d40">#00000d40</color>
+ <color name="i_am_color_d41">#00000d41</color>
+ <color name="i_am_color_d42">#00000d42</color>
+ <color name="i_am_color_d43">#00000d43</color>
+ <color name="i_am_color_d44">#00000d44</color>
+ <color name="i_am_color_d45">#00000d45</color>
+ <color name="i_am_color_d46">#00000d46</color>
+ <color name="i_am_color_d47">#00000d47</color>
+ <color name="i_am_color_d48">#00000d48</color>
+ <color name="i_am_color_d49">#00000d49</color>
+ <color name="i_am_color_d4a">#00000d4a</color>
+ <color name="i_am_color_d4b">#00000d4b</color>
+ <color name="i_am_color_d4c">#00000d4c</color>
+ <color name="i_am_color_d4d">#00000d4d</color>
+ <color name="i_am_color_d4e">#00000d4e</color>
+ <color name="i_am_color_d4f">#00000d4f</color>
+ <color name="i_am_color_d50">#00000d50</color>
+ <color name="i_am_color_d51">#00000d51</color>
+ <color name="i_am_color_d52">#00000d52</color>
+ <color name="i_am_color_d53">#00000d53</color>
+ <color name="i_am_color_d54">#00000d54</color>
+ <color name="i_am_color_d55">#00000d55</color>
+ <color name="i_am_color_d56">#00000d56</color>
+ <color name="i_am_color_d57">#00000d57</color>
+ <color name="i_am_color_d58">#00000d58</color>
+ <color name="i_am_color_d59">#00000d59</color>
+ <color name="i_am_color_d5a">#00000d5a</color>
+ <color name="i_am_color_d5b">#00000d5b</color>
+ <color name="i_am_color_d5c">#00000d5c</color>
+ <color name="i_am_color_d5d">#00000d5d</color>
+ <color name="i_am_color_d5e">#00000d5e</color>
+ <color name="i_am_color_d5f">#00000d5f</color>
+ <color name="i_am_color_d60">#00000d60</color>
+ <color name="i_am_color_d61">#00000d61</color>
+ <color name="i_am_color_d62">#00000d62</color>
+ <color name="i_am_color_d63">#00000d63</color>
+ <color name="i_am_color_d64">#00000d64</color>
+ <color name="i_am_color_d65">#00000d65</color>
+ <color name="i_am_color_d66">#00000d66</color>
+ <color name="i_am_color_d67">#00000d67</color>
+ <color name="i_am_color_d68">#00000d68</color>
+ <color name="i_am_color_d69">#00000d69</color>
+ <color name="i_am_color_d6a">#00000d6a</color>
+ <color name="i_am_color_d6b">#00000d6b</color>
+ <color name="i_am_color_d6c">#00000d6c</color>
+ <color name="i_am_color_d6d">#00000d6d</color>
+ <color name="i_am_color_d6e">#00000d6e</color>
+ <color name="i_am_color_d6f">#00000d6f</color>
+ <color name="i_am_color_d70">#00000d70</color>
+ <color name="i_am_color_d71">#00000d71</color>
+ <color name="i_am_color_d72">#00000d72</color>
+ <color name="i_am_color_d73">#00000d73</color>
+ <color name="i_am_color_d74">#00000d74</color>
+ <color name="i_am_color_d75">#00000d75</color>
+ <color name="i_am_color_d76">#00000d76</color>
+ <color name="i_am_color_d77">#00000d77</color>
+ <color name="i_am_color_d78">#00000d78</color>
+ <color name="i_am_color_d79">#00000d79</color>
+ <color name="i_am_color_d7a">#00000d7a</color>
+ <color name="i_am_color_d7b">#00000d7b</color>
+ <color name="i_am_color_d7c">#00000d7c</color>
+ <color name="i_am_color_d7d">#00000d7d</color>
+ <color name="i_am_color_d7e">#00000d7e</color>
+ <color name="i_am_color_d7f">#00000d7f</color>
+ <color name="i_am_color_d80">#00000d80</color>
+ <color name="i_am_color_d81">#00000d81</color>
+ <color name="i_am_color_d82">#00000d82</color>
+ <color name="i_am_color_d83">#00000d83</color>
+ <color name="i_am_color_d84">#00000d84</color>
+ <color name="i_am_color_d85">#00000d85</color>
+ <color name="i_am_color_d86">#00000d86</color>
+ <color name="i_am_color_d87">#00000d87</color>
+ <color name="i_am_color_d88">#00000d88</color>
+ <color name="i_am_color_d89">#00000d89</color>
+ <color name="i_am_color_d8a">#00000d8a</color>
+ <color name="i_am_color_d8b">#00000d8b</color>
+ <color name="i_am_color_d8c">#00000d8c</color>
+ <color name="i_am_color_d8d">#00000d8d</color>
+ <color name="i_am_color_d8e">#00000d8e</color>
+ <color name="i_am_color_d8f">#00000d8f</color>
+ <color name="i_am_color_d90">#00000d90</color>
+ <color name="i_am_color_d91">#00000d91</color>
+ <color name="i_am_color_d92">#00000d92</color>
+ <color name="i_am_color_d93">#00000d93</color>
+ <color name="i_am_color_d94">#00000d94</color>
+ <color name="i_am_color_d95">#00000d95</color>
+ <color name="i_am_color_d96">#00000d96</color>
+ <color name="i_am_color_d97">#00000d97</color>
+ <color name="i_am_color_d98">#00000d98</color>
+ <color name="i_am_color_d99">#00000d99</color>
+ <color name="i_am_color_d9a">#00000d9a</color>
+ <color name="i_am_color_d9b">#00000d9b</color>
+ <color name="i_am_color_d9c">#00000d9c</color>
+ <color name="i_am_color_d9d">#00000d9d</color>
+ <color name="i_am_color_d9e">#00000d9e</color>
+ <color name="i_am_color_d9f">#00000d9f</color>
+ <color name="i_am_color_da0">#00000da0</color>
+ <color name="i_am_color_da1">#00000da1</color>
+ <color name="i_am_color_da2">#00000da2</color>
+ <color name="i_am_color_da3">#00000da3</color>
+ <color name="i_am_color_da4">#00000da4</color>
+ <color name="i_am_color_da5">#00000da5</color>
+ <color name="i_am_color_da6">#00000da6</color>
+ <color name="i_am_color_da7">#00000da7</color>
+ <color name="i_am_color_da8">#00000da8</color>
+ <color name="i_am_color_da9">#00000da9</color>
+ <color name="i_am_color_daa">#00000daa</color>
+ <color name="i_am_color_dab">#00000dab</color>
+ <color name="i_am_color_dac">#00000dac</color>
+ <color name="i_am_color_dad">#00000dad</color>
+ <color name="i_am_color_dae">#00000dae</color>
+ <color name="i_am_color_daf">#00000daf</color>
+ <color name="i_am_color_db0">#00000db0</color>
+ <color name="i_am_color_db1">#00000db1</color>
+ <color name="i_am_color_db2">#00000db2</color>
+ <color name="i_am_color_db3">#00000db3</color>
+ <color name="i_am_color_db4">#00000db4</color>
+ <color name="i_am_color_db5">#00000db5</color>
+ <color name="i_am_color_db6">#00000db6</color>
+ <color name="i_am_color_db7">#00000db7</color>
+ <color name="i_am_color_db8">#00000db8</color>
+ <color name="i_am_color_db9">#00000db9</color>
+ <color name="i_am_color_dba">#00000dba</color>
+ <color name="i_am_color_dbb">#00000dbb</color>
+ <color name="i_am_color_dbc">#00000dbc</color>
+ <color name="i_am_color_dbd">#00000dbd</color>
+ <color name="i_am_color_dbe">#00000dbe</color>
+ <color name="i_am_color_dbf">#00000dbf</color>
+ <color name="i_am_color_dc0">#00000dc0</color>
+ <color name="i_am_color_dc1">#00000dc1</color>
+ <color name="i_am_color_dc2">#00000dc2</color>
+ <color name="i_am_color_dc3">#00000dc3</color>
+ <color name="i_am_color_dc4">#00000dc4</color>
+ <color name="i_am_color_dc5">#00000dc5</color>
+ <color name="i_am_color_dc6">#00000dc6</color>
+ <color name="i_am_color_dc7">#00000dc7</color>
+ <color name="i_am_color_dc8">#00000dc8</color>
+ <color name="i_am_color_dc9">#00000dc9</color>
+ <color name="i_am_color_dca">#00000dca</color>
+ <color name="i_am_color_dcb">#00000dcb</color>
+ <color name="i_am_color_dcc">#00000dcc</color>
+ <color name="i_am_color_dcd">#00000dcd</color>
+ <color name="i_am_color_dce">#00000dce</color>
+ <color name="i_am_color_dcf">#00000dcf</color>
+ <color name="i_am_color_dd0">#00000dd0</color>
+ <color name="i_am_color_dd1">#00000dd1</color>
+ <color name="i_am_color_dd2">#00000dd2</color>
+ <color name="i_am_color_dd3">#00000dd3</color>
+ <color name="i_am_color_dd4">#00000dd4</color>
+ <color name="i_am_color_dd5">#00000dd5</color>
+ <color name="i_am_color_dd6">#00000dd6</color>
+ <color name="i_am_color_dd7">#00000dd7</color>
+ <color name="i_am_color_dd8">#00000dd8</color>
+ <color name="i_am_color_dd9">#00000dd9</color>
+ <color name="i_am_color_dda">#00000dda</color>
+ <color name="i_am_color_ddb">#00000ddb</color>
+ <color name="i_am_color_ddc">#00000ddc</color>
+ <color name="i_am_color_ddd">#00000ddd</color>
+ <color name="i_am_color_dde">#00000dde</color>
+ <color name="i_am_color_ddf">#00000ddf</color>
+ <color name="i_am_color_de0">#00000de0</color>
+ <color name="i_am_color_de1">#00000de1</color>
+ <color name="i_am_color_de2">#00000de2</color>
+ <color name="i_am_color_de3">#00000de3</color>
+ <color name="i_am_color_de4">#00000de4</color>
+ <color name="i_am_color_de5">#00000de5</color>
+ <color name="i_am_color_de6">#00000de6</color>
+ <color name="i_am_color_de7">#00000de7</color>
+ <color name="i_am_color_de8">#00000de8</color>
+ <color name="i_am_color_de9">#00000de9</color>
+ <color name="i_am_color_dea">#00000dea</color>
+ <color name="i_am_color_deb">#00000deb</color>
+ <color name="i_am_color_dec">#00000dec</color>
+ <color name="i_am_color_ded">#00000ded</color>
+ <color name="i_am_color_dee">#00000dee</color>
+ <color name="i_am_color_def">#00000def</color>
+ <color name="i_am_color_df0">#00000df0</color>
+ <color name="i_am_color_df1">#00000df1</color>
+ <color name="i_am_color_df2">#00000df2</color>
+ <color name="i_am_color_df3">#00000df3</color>
+ <color name="i_am_color_df4">#00000df4</color>
+ <color name="i_am_color_df5">#00000df5</color>
+ <color name="i_am_color_df6">#00000df6</color>
+ <color name="i_am_color_df7">#00000df7</color>
+ <color name="i_am_color_df8">#00000df8</color>
+ <color name="i_am_color_df9">#00000df9</color>
+ <color name="i_am_color_dfa">#00000dfa</color>
+ <color name="i_am_color_dfb">#00000dfb</color>
+ <color name="i_am_color_dfc">#00000dfc</color>
+ <color name="i_am_color_dfd">#00000dfd</color>
+ <color name="i_am_color_dfe">#00000dfe</color>
+ <color name="i_am_color_dff">#00000dff</color>
+ <color name="i_am_color_e00">#00000e00</color>
+ <color name="i_am_color_e01">#00000e01</color>
+ <color name="i_am_color_e02">#00000e02</color>
+ <color name="i_am_color_e03">#00000e03</color>
+ <color name="i_am_color_e04">#00000e04</color>
+ <color name="i_am_color_e05">#00000e05</color>
+ <color name="i_am_color_e06">#00000e06</color>
+ <color name="i_am_color_e07">#00000e07</color>
+ <color name="i_am_color_e08">#00000e08</color>
+ <color name="i_am_color_e09">#00000e09</color>
+ <color name="i_am_color_e0a">#00000e0a</color>
+ <color name="i_am_color_e0b">#00000e0b</color>
+ <color name="i_am_color_e0c">#00000e0c</color>
+ <color name="i_am_color_e0d">#00000e0d</color>
+ <color name="i_am_color_e0e">#00000e0e</color>
+ <color name="i_am_color_e0f">#00000e0f</color>
+ <color name="i_am_color_e10">#00000e10</color>
+ <color name="i_am_color_e11">#00000e11</color>
+ <color name="i_am_color_e12">#00000e12</color>
+ <color name="i_am_color_e13">#00000e13</color>
+ <color name="i_am_color_e14">#00000e14</color>
+ <color name="i_am_color_e15">#00000e15</color>
+ <color name="i_am_color_e16">#00000e16</color>
+ <color name="i_am_color_e17">#00000e17</color>
+ <color name="i_am_color_e18">#00000e18</color>
+ <color name="i_am_color_e19">#00000e19</color>
+ <color name="i_am_color_e1a">#00000e1a</color>
+ <color name="i_am_color_e1b">#00000e1b</color>
+ <color name="i_am_color_e1c">#00000e1c</color>
+ <color name="i_am_color_e1d">#00000e1d</color>
+ <color name="i_am_color_e1e">#00000e1e</color>
+ <color name="i_am_color_e1f">#00000e1f</color>
+ <color name="i_am_color_e20">#00000e20</color>
+ <color name="i_am_color_e21">#00000e21</color>
+ <color name="i_am_color_e22">#00000e22</color>
+ <color name="i_am_color_e23">#00000e23</color>
+ <color name="i_am_color_e24">#00000e24</color>
+ <color name="i_am_color_e25">#00000e25</color>
+ <color name="i_am_color_e26">#00000e26</color>
+ <color name="i_am_color_e27">#00000e27</color>
+ <color name="i_am_color_e28">#00000e28</color>
+ <color name="i_am_color_e29">#00000e29</color>
+ <color name="i_am_color_e2a">#00000e2a</color>
+ <color name="i_am_color_e2b">#00000e2b</color>
+ <color name="i_am_color_e2c">#00000e2c</color>
+ <color name="i_am_color_e2d">#00000e2d</color>
+ <color name="i_am_color_e2e">#00000e2e</color>
+ <color name="i_am_color_e2f">#00000e2f</color>
+ <color name="i_am_color_e30">#00000e30</color>
+ <color name="i_am_color_e31">#00000e31</color>
+ <color name="i_am_color_e32">#00000e32</color>
+ <color name="i_am_color_e33">#00000e33</color>
+ <color name="i_am_color_e34">#00000e34</color>
+ <color name="i_am_color_e35">#00000e35</color>
+ <color name="i_am_color_e36">#00000e36</color>
+ <color name="i_am_color_e37">#00000e37</color>
+ <color name="i_am_color_e38">#00000e38</color>
+ <color name="i_am_color_e39">#00000e39</color>
+ <color name="i_am_color_e3a">#00000e3a</color>
+ <color name="i_am_color_e3b">#00000e3b</color>
+ <color name="i_am_color_e3c">#00000e3c</color>
+ <color name="i_am_color_e3d">#00000e3d</color>
+ <color name="i_am_color_e3e">#00000e3e</color>
+ <color name="i_am_color_e3f">#00000e3f</color>
+ <color name="i_am_color_e40">#00000e40</color>
+ <color name="i_am_color_e41">#00000e41</color>
+ <color name="i_am_color_e42">#00000e42</color>
+ <color name="i_am_color_e43">#00000e43</color>
+ <color name="i_am_color_e44">#00000e44</color>
+ <color name="i_am_color_e45">#00000e45</color>
+ <color name="i_am_color_e46">#00000e46</color>
+ <color name="i_am_color_e47">#00000e47</color>
+ <color name="i_am_color_e48">#00000e48</color>
+ <color name="i_am_color_e49">#00000e49</color>
+ <color name="i_am_color_e4a">#00000e4a</color>
+ <color name="i_am_color_e4b">#00000e4b</color>
+ <color name="i_am_color_e4c">#00000e4c</color>
+ <color name="i_am_color_e4d">#00000e4d</color>
+ <color name="i_am_color_e4e">#00000e4e</color>
+ <color name="i_am_color_e4f">#00000e4f</color>
+ <color name="i_am_color_e50">#00000e50</color>
+ <color name="i_am_color_e51">#00000e51</color>
+ <color name="i_am_color_e52">#00000e52</color>
+ <color name="i_am_color_e53">#00000e53</color>
+ <color name="i_am_color_e54">#00000e54</color>
+ <color name="i_am_color_e55">#00000e55</color>
+ <color name="i_am_color_e56">#00000e56</color>
+ <color name="i_am_color_e57">#00000e57</color>
+ <color name="i_am_color_e58">#00000e58</color>
+ <color name="i_am_color_e59">#00000e59</color>
+ <color name="i_am_color_e5a">#00000e5a</color>
+ <color name="i_am_color_e5b">#00000e5b</color>
+ <color name="i_am_color_e5c">#00000e5c</color>
+ <color name="i_am_color_e5d">#00000e5d</color>
+ <color name="i_am_color_e5e">#00000e5e</color>
+ <color name="i_am_color_e5f">#00000e5f</color>
+ <color name="i_am_color_e60">#00000e60</color>
+ <color name="i_am_color_e61">#00000e61</color>
+ <color name="i_am_color_e62">#00000e62</color>
+ <color name="i_am_color_e63">#00000e63</color>
+ <color name="i_am_color_e64">#00000e64</color>
+ <color name="i_am_color_e65">#00000e65</color>
+ <color name="i_am_color_e66">#00000e66</color>
+ <color name="i_am_color_e67">#00000e67</color>
+ <color name="i_am_color_e68">#00000e68</color>
+ <color name="i_am_color_e69">#00000e69</color>
+ <color name="i_am_color_e6a">#00000e6a</color>
+ <color name="i_am_color_e6b">#00000e6b</color>
+ <color name="i_am_color_e6c">#00000e6c</color>
+ <color name="i_am_color_e6d">#00000e6d</color>
+ <color name="i_am_color_e6e">#00000e6e</color>
+ <color name="i_am_color_e6f">#00000e6f</color>
+ <color name="i_am_color_e70">#00000e70</color>
+ <color name="i_am_color_e71">#00000e71</color>
+ <color name="i_am_color_e72">#00000e72</color>
+ <color name="i_am_color_e73">#00000e73</color>
+ <color name="i_am_color_e74">#00000e74</color>
+ <color name="i_am_color_e75">#00000e75</color>
+ <color name="i_am_color_e76">#00000e76</color>
+ <color name="i_am_color_e77">#00000e77</color>
+ <color name="i_am_color_e78">#00000e78</color>
+ <color name="i_am_color_e79">#00000e79</color>
+ <color name="i_am_color_e7a">#00000e7a</color>
+ <color name="i_am_color_e7b">#00000e7b</color>
+ <color name="i_am_color_e7c">#00000e7c</color>
+ <color name="i_am_color_e7d">#00000e7d</color>
+ <color name="i_am_color_e7e">#00000e7e</color>
+ <color name="i_am_color_e7f">#00000e7f</color>
+ <color name="i_am_color_e80">#00000e80</color>
+ <color name="i_am_color_e81">#00000e81</color>
+ <color name="i_am_color_e82">#00000e82</color>
+ <color name="i_am_color_e83">#00000e83</color>
+ <color name="i_am_color_e84">#00000e84</color>
+ <color name="i_am_color_e85">#00000e85</color>
+ <color name="i_am_color_e86">#00000e86</color>
+ <color name="i_am_color_e87">#00000e87</color>
+ <color name="i_am_color_e88">#00000e88</color>
+ <color name="i_am_color_e89">#00000e89</color>
+ <color name="i_am_color_e8a">#00000e8a</color>
+ <color name="i_am_color_e8b">#00000e8b</color>
+ <color name="i_am_color_e8c">#00000e8c</color>
+ <color name="i_am_color_e8d">#00000e8d</color>
+ <color name="i_am_color_e8e">#00000e8e</color>
+ <color name="i_am_color_e8f">#00000e8f</color>
+ <color name="i_am_color_e90">#00000e90</color>
+ <color name="i_am_color_e91">#00000e91</color>
+ <color name="i_am_color_e92">#00000e92</color>
+ <color name="i_am_color_e93">#00000e93</color>
+ <color name="i_am_color_e94">#00000e94</color>
+ <color name="i_am_color_e95">#00000e95</color>
+ <color name="i_am_color_e96">#00000e96</color>
+ <color name="i_am_color_e97">#00000e97</color>
+ <color name="i_am_color_e98">#00000e98</color>
+ <color name="i_am_color_e99">#00000e99</color>
+ <color name="i_am_color_e9a">#00000e9a</color>
+ <color name="i_am_color_e9b">#00000e9b</color>
+ <color name="i_am_color_e9c">#00000e9c</color>
+ <color name="i_am_color_e9d">#00000e9d</color>
+ <color name="i_am_color_e9e">#00000e9e</color>
+ <color name="i_am_color_e9f">#00000e9f</color>
+ <color name="i_am_color_ea0">#00000ea0</color>
+ <color name="i_am_color_ea1">#00000ea1</color>
+ <color name="i_am_color_ea2">#00000ea2</color>
+ <color name="i_am_color_ea3">#00000ea3</color>
+ <color name="i_am_color_ea4">#00000ea4</color>
+ <color name="i_am_color_ea5">#00000ea5</color>
+ <color name="i_am_color_ea6">#00000ea6</color>
+ <color name="i_am_color_ea7">#00000ea7</color>
+ <color name="i_am_color_ea8">#00000ea8</color>
+ <color name="i_am_color_ea9">#00000ea9</color>
+ <color name="i_am_color_eaa">#00000eaa</color>
+ <color name="i_am_color_eab">#00000eab</color>
+ <color name="i_am_color_eac">#00000eac</color>
+ <color name="i_am_color_ead">#00000ead</color>
+ <color name="i_am_color_eae">#00000eae</color>
+ <color name="i_am_color_eaf">#00000eaf</color>
+ <color name="i_am_color_eb0">#00000eb0</color>
+ <color name="i_am_color_eb1">#00000eb1</color>
+ <color name="i_am_color_eb2">#00000eb2</color>
+ <color name="i_am_color_eb3">#00000eb3</color>
+ <color name="i_am_color_eb4">#00000eb4</color>
+ <color name="i_am_color_eb5">#00000eb5</color>
+ <color name="i_am_color_eb6">#00000eb6</color>
+ <color name="i_am_color_eb7">#00000eb7</color>
+ <color name="i_am_color_eb8">#00000eb8</color>
+ <color name="i_am_color_eb9">#00000eb9</color>
+ <color name="i_am_color_eba">#00000eba</color>
+ <color name="i_am_color_ebb">#00000ebb</color>
+ <color name="i_am_color_ebc">#00000ebc</color>
+ <color name="i_am_color_ebd">#00000ebd</color>
+ <color name="i_am_color_ebe">#00000ebe</color>
+ <color name="i_am_color_ebf">#00000ebf</color>
+ <color name="i_am_color_ec0">#00000ec0</color>
+ <color name="i_am_color_ec1">#00000ec1</color>
+ <color name="i_am_color_ec2">#00000ec2</color>
+ <color name="i_am_color_ec3">#00000ec3</color>
+ <color name="i_am_color_ec4">#00000ec4</color>
+ <color name="i_am_color_ec5">#00000ec5</color>
+ <color name="i_am_color_ec6">#00000ec6</color>
+ <color name="i_am_color_ec7">#00000ec7</color>
+ <color name="i_am_color_ec8">#00000ec8</color>
+ <color name="i_am_color_ec9">#00000ec9</color>
+ <color name="i_am_color_eca">#00000eca</color>
+ <color name="i_am_color_ecb">#00000ecb</color>
+ <color name="i_am_color_ecc">#00000ecc</color>
+ <color name="i_am_color_ecd">#00000ecd</color>
+ <color name="i_am_color_ece">#00000ece</color>
+ <color name="i_am_color_ecf">#00000ecf</color>
+ <color name="i_am_color_ed0">#00000ed0</color>
+ <color name="i_am_color_ed1">#00000ed1</color>
+ <color name="i_am_color_ed2">#00000ed2</color>
+ <color name="i_am_color_ed3">#00000ed3</color>
+ <color name="i_am_color_ed4">#00000ed4</color>
+ <color name="i_am_color_ed5">#00000ed5</color>
+ <color name="i_am_color_ed6">#00000ed6</color>
+ <color name="i_am_color_ed7">#00000ed7</color>
+ <color name="i_am_color_ed8">#00000ed8</color>
+ <color name="i_am_color_ed9">#00000ed9</color>
+ <color name="i_am_color_eda">#00000eda</color>
+ <color name="i_am_color_edb">#00000edb</color>
+ <color name="i_am_color_edc">#00000edc</color>
+ <color name="i_am_color_edd">#00000edd</color>
+ <color name="i_am_color_ede">#00000ede</color>
+ <color name="i_am_color_edf">#00000edf</color>
+ <color name="i_am_color_ee0">#00000ee0</color>
+ <color name="i_am_color_ee1">#00000ee1</color>
+ <color name="i_am_color_ee2">#00000ee2</color>
+ <color name="i_am_color_ee3">#00000ee3</color>
+ <color name="i_am_color_ee4">#00000ee4</color>
+ <color name="i_am_color_ee5">#00000ee5</color>
+ <color name="i_am_color_ee6">#00000ee6</color>
+ <color name="i_am_color_ee7">#00000ee7</color>
+ <color name="i_am_color_ee8">#00000ee8</color>
+ <color name="i_am_color_ee9">#00000ee9</color>
+ <color name="i_am_color_eea">#00000eea</color>
+ <color name="i_am_color_eeb">#00000eeb</color>
+ <color name="i_am_color_eec">#00000eec</color>
+ <color name="i_am_color_eed">#00000eed</color>
+ <color name="i_am_color_eee">#00000eee</color>
+ <color name="i_am_color_eef">#00000eef</color>
+ <color name="i_am_color_ef0">#00000ef0</color>
+ <color name="i_am_color_ef1">#00000ef1</color>
+ <color name="i_am_color_ef2">#00000ef2</color>
+ <color name="i_am_color_ef3">#00000ef3</color>
+ <color name="i_am_color_ef4">#00000ef4</color>
+ <color name="i_am_color_ef5">#00000ef5</color>
+ <color name="i_am_color_ef6">#00000ef6</color>
+ <color name="i_am_color_ef7">#00000ef7</color>
+ <color name="i_am_color_ef8">#00000ef8</color>
+ <color name="i_am_color_ef9">#00000ef9</color>
+ <color name="i_am_color_efa">#00000efa</color>
+ <color name="i_am_color_efb">#00000efb</color>
+ <color name="i_am_color_efc">#00000efc</color>
+ <color name="i_am_color_efd">#00000efd</color>
+ <color name="i_am_color_efe">#00000efe</color>
+ <color name="i_am_color_eff">#00000eff</color>
+ <color name="i_am_color_f00">#00000f00</color>
+ <color name="i_am_color_f01">#00000f01</color>
+ <color name="i_am_color_f02">#00000f02</color>
+ <color name="i_am_color_f03">#00000f03</color>
+ <color name="i_am_color_f04">#00000f04</color>
+ <color name="i_am_color_f05">#00000f05</color>
+ <color name="i_am_color_f06">#00000f06</color>
+ <color name="i_am_color_f07">#00000f07</color>
+ <color name="i_am_color_f08">#00000f08</color>
+ <color name="i_am_color_f09">#00000f09</color>
+ <color name="i_am_color_f0a">#00000f0a</color>
+ <color name="i_am_color_f0b">#00000f0b</color>
+ <color name="i_am_color_f0c">#00000f0c</color>
+ <color name="i_am_color_f0d">#00000f0d</color>
+ <color name="i_am_color_f0e">#00000f0e</color>
+ <color name="i_am_color_f0f">#00000f0f</color>
+ <color name="i_am_color_f10">#00000f10</color>
+ <color name="i_am_color_f11">#00000f11</color>
+ <color name="i_am_color_f12">#00000f12</color>
+ <color name="i_am_color_f13">#00000f13</color>
+ <color name="i_am_color_f14">#00000f14</color>
+ <color name="i_am_color_f15">#00000f15</color>
+ <color name="i_am_color_f16">#00000f16</color>
+ <color name="i_am_color_f17">#00000f17</color>
+ <color name="i_am_color_f18">#00000f18</color>
+ <color name="i_am_color_f19">#00000f19</color>
+ <color name="i_am_color_f1a">#00000f1a</color>
+ <color name="i_am_color_f1b">#00000f1b</color>
+ <color name="i_am_color_f1c">#00000f1c</color>
+ <color name="i_am_color_f1d">#00000f1d</color>
+ <color name="i_am_color_f1e">#00000f1e</color>
+ <color name="i_am_color_f1f">#00000f1f</color>
+ <color name="i_am_color_f20">#00000f20</color>
+ <color name="i_am_color_f21">#00000f21</color>
+ <color name="i_am_color_f22">#00000f22</color>
+ <color name="i_am_color_f23">#00000f23</color>
+ <color name="i_am_color_f24">#00000f24</color>
+ <color name="i_am_color_f25">#00000f25</color>
+ <color name="i_am_color_f26">#00000f26</color>
+ <color name="i_am_color_f27">#00000f27</color>
+ <color name="i_am_color_f28">#00000f28</color>
+ <color name="i_am_color_f29">#00000f29</color>
+ <color name="i_am_color_f2a">#00000f2a</color>
+ <color name="i_am_color_f2b">#00000f2b</color>
+ <color name="i_am_color_f2c">#00000f2c</color>
+ <color name="i_am_color_f2d">#00000f2d</color>
+ <color name="i_am_color_f2e">#00000f2e</color>
+ <color name="i_am_color_f2f">#00000f2f</color>
+ <color name="i_am_color_f30">#00000f30</color>
+ <color name="i_am_color_f31">#00000f31</color>
+ <color name="i_am_color_f32">#00000f32</color>
+ <color name="i_am_color_f33">#00000f33</color>
+ <color name="i_am_color_f34">#00000f34</color>
+ <color name="i_am_color_f35">#00000f35</color>
+ <color name="i_am_color_f36">#00000f36</color>
+ <color name="i_am_color_f37">#00000f37</color>
+ <color name="i_am_color_f38">#00000f38</color>
+ <color name="i_am_color_f39">#00000f39</color>
+ <color name="i_am_color_f3a">#00000f3a</color>
+ <color name="i_am_color_f3b">#00000f3b</color>
+ <color name="i_am_color_f3c">#00000f3c</color>
+ <color name="i_am_color_f3d">#00000f3d</color>
+ <color name="i_am_color_f3e">#00000f3e</color>
+ <color name="i_am_color_f3f">#00000f3f</color>
+ <color name="i_am_color_f40">#00000f40</color>
+ <color name="i_am_color_f41">#00000f41</color>
+ <color name="i_am_color_f42">#00000f42</color>
+ <color name="i_am_color_f43">#00000f43</color>
+ <color name="i_am_color_f44">#00000f44</color>
+ <color name="i_am_color_f45">#00000f45</color>
+ <color name="i_am_color_f46">#00000f46</color>
+ <color name="i_am_color_f47">#00000f47</color>
+ <color name="i_am_color_f48">#00000f48</color>
+ <color name="i_am_color_f49">#00000f49</color>
+ <color name="i_am_color_f4a">#00000f4a</color>
+ <color name="i_am_color_f4b">#00000f4b</color>
+ <color name="i_am_color_f4c">#00000f4c</color>
+ <color name="i_am_color_f4d">#00000f4d</color>
+ <color name="i_am_color_f4e">#00000f4e</color>
+ <color name="i_am_color_f4f">#00000f4f</color>
+ <color name="i_am_color_f50">#00000f50</color>
+ <color name="i_am_color_f51">#00000f51</color>
+ <color name="i_am_color_f52">#00000f52</color>
+ <color name="i_am_color_f53">#00000f53</color>
+ <color name="i_am_color_f54">#00000f54</color>
+ <color name="i_am_color_f55">#00000f55</color>
+ <color name="i_am_color_f56">#00000f56</color>
+ <color name="i_am_color_f57">#00000f57</color>
+ <color name="i_am_color_f58">#00000f58</color>
+ <color name="i_am_color_f59">#00000f59</color>
+ <color name="i_am_color_f5a">#00000f5a</color>
+ <color name="i_am_color_f5b">#00000f5b</color>
+ <color name="i_am_color_f5c">#00000f5c</color>
+ <color name="i_am_color_f5d">#00000f5d</color>
+ <color name="i_am_color_f5e">#00000f5e</color>
+ <color name="i_am_color_f5f">#00000f5f</color>
+ <color name="i_am_color_f60">#00000f60</color>
+ <color name="i_am_color_f61">#00000f61</color>
+ <color name="i_am_color_f62">#00000f62</color>
+ <color name="i_am_color_f63">#00000f63</color>
+ <color name="i_am_color_f64">#00000f64</color>
+ <color name="i_am_color_f65">#00000f65</color>
+ <color name="i_am_color_f66">#00000f66</color>
+ <color name="i_am_color_f67">#00000f67</color>
+ <color name="i_am_color_f68">#00000f68</color>
+ <color name="i_am_color_f69">#00000f69</color>
+ <color name="i_am_color_f6a">#00000f6a</color>
+ <color name="i_am_color_f6b">#00000f6b</color>
+ <color name="i_am_color_f6c">#00000f6c</color>
+ <color name="i_am_color_f6d">#00000f6d</color>
+ <color name="i_am_color_f6e">#00000f6e</color>
+ <color name="i_am_color_f6f">#00000f6f</color>
+ <color name="i_am_color_f70">#00000f70</color>
+ <color name="i_am_color_f71">#00000f71</color>
+ <color name="i_am_color_f72">#00000f72</color>
+ <color name="i_am_color_f73">#00000f73</color>
+ <color name="i_am_color_f74">#00000f74</color>
+ <color name="i_am_color_f75">#00000f75</color>
+ <color name="i_am_color_f76">#00000f76</color>
+ <color name="i_am_color_f77">#00000f77</color>
+ <color name="i_am_color_f78">#00000f78</color>
+ <color name="i_am_color_f79">#00000f79</color>
+ <color name="i_am_color_f7a">#00000f7a</color>
+ <color name="i_am_color_f7b">#00000f7b</color>
+ <color name="i_am_color_f7c">#00000f7c</color>
+ <color name="i_am_color_f7d">#00000f7d</color>
+ <color name="i_am_color_f7e">#00000f7e</color>
+ <color name="i_am_color_f7f">#00000f7f</color>
+ <color name="i_am_color_f80">#00000f80</color>
+ <color name="i_am_color_f81">#00000f81</color>
+ <color name="i_am_color_f82">#00000f82</color>
+ <color name="i_am_color_f83">#00000f83</color>
+ <color name="i_am_color_f84">#00000f84</color>
+ <color name="i_am_color_f85">#00000f85</color>
+ <color name="i_am_color_f86">#00000f86</color>
+ <color name="i_am_color_f87">#00000f87</color>
+ <color name="i_am_color_f88">#00000f88</color>
+ <color name="i_am_color_f89">#00000f89</color>
+ <color name="i_am_color_f8a">#00000f8a</color>
+ <color name="i_am_color_f8b">#00000f8b</color>
+ <color name="i_am_color_f8c">#00000f8c</color>
+ <color name="i_am_color_f8d">#00000f8d</color>
+ <color name="i_am_color_f8e">#00000f8e</color>
+ <color name="i_am_color_f8f">#00000f8f</color>
+ <color name="i_am_color_f90">#00000f90</color>
+ <color name="i_am_color_f91">#00000f91</color>
+ <color name="i_am_color_f92">#00000f92</color>
+ <color name="i_am_color_f93">#00000f93</color>
+ <color name="i_am_color_f94">#00000f94</color>
+ <color name="i_am_color_f95">#00000f95</color>
+ <color name="i_am_color_f96">#00000f96</color>
+ <color name="i_am_color_f97">#00000f97</color>
+ <color name="i_am_color_f98">#00000f98</color>
+ <color name="i_am_color_f99">#00000f99</color>
+ <color name="i_am_color_f9a">#00000f9a</color>
+ <color name="i_am_color_f9b">#00000f9b</color>
+ <color name="i_am_color_f9c">#00000f9c</color>
+ <color name="i_am_color_f9d">#00000f9d</color>
+ <color name="i_am_color_f9e">#00000f9e</color>
+ <color name="i_am_color_f9f">#00000f9f</color>
+ <color name="i_am_color_fa0">#00000fa0</color>
+ <color name="i_am_color_fa1">#00000fa1</color>
+ <color name="i_am_color_fa2">#00000fa2</color>
+ <color name="i_am_color_fa3">#00000fa3</color>
+ <color name="i_am_color_fa4">#00000fa4</color>
+ <color name="i_am_color_fa5">#00000fa5</color>
+ <color name="i_am_color_fa6">#00000fa6</color>
+ <color name="i_am_color_fa7">#00000fa7</color>
+ <color name="i_am_color_fa8">#00000fa8</color>
+ <color name="i_am_color_fa9">#00000fa9</color>
+ <color name="i_am_color_faa">#00000faa</color>
+ <color name="i_am_color_fab">#00000fab</color>
+ <color name="i_am_color_fac">#00000fac</color>
+ <color name="i_am_color_fad">#00000fad</color>
+ <color name="i_am_color_fae">#00000fae</color>
+ <color name="i_am_color_faf">#00000faf</color>
+ <color name="i_am_color_fb0">#00000fb0</color>
+ <color name="i_am_color_fb1">#00000fb1</color>
+ <color name="i_am_color_fb2">#00000fb2</color>
+ <color name="i_am_color_fb3">#00000fb3</color>
+ <color name="i_am_color_fb4">#00000fb4</color>
+ <color name="i_am_color_fb5">#00000fb5</color>
+ <color name="i_am_color_fb6">#00000fb6</color>
+ <color name="i_am_color_fb7">#00000fb7</color>
+ <color name="i_am_color_fb8">#00000fb8</color>
+ <color name="i_am_color_fb9">#00000fb9</color>
+ <color name="i_am_color_fba">#00000fba</color>
+ <color name="i_am_color_fbb">#00000fbb</color>
+ <color name="i_am_color_fbc">#00000fbc</color>
+ <color name="i_am_color_fbd">#00000fbd</color>
+ <color name="i_am_color_fbe">#00000fbe</color>
+ <color name="i_am_color_fbf">#00000fbf</color>
+ <color name="i_am_color_fc0">#00000fc0</color>
+ <color name="i_am_color_fc1">#00000fc1</color>
+ <color name="i_am_color_fc2">#00000fc2</color>
+ <color name="i_am_color_fc3">#00000fc3</color>
+ <color name="i_am_color_fc4">#00000fc4</color>
+ <color name="i_am_color_fc5">#00000fc5</color>
+ <color name="i_am_color_fc6">#00000fc6</color>
+ <color name="i_am_color_fc7">#00000fc7</color>
+ <color name="i_am_color_fc8">#00000fc8</color>
+ <color name="i_am_color_fc9">#00000fc9</color>
+ <color name="i_am_color_fca">#00000fca</color>
+ <color name="i_am_color_fcb">#00000fcb</color>
+ <color name="i_am_color_fcc">#00000fcc</color>
+ <color name="i_am_color_fcd">#00000fcd</color>
+ <color name="i_am_color_fce">#00000fce</color>
+ <color name="i_am_color_fcf">#00000fcf</color>
+ <color name="i_am_color_fd0">#00000fd0</color>
+ <color name="i_am_color_fd1">#00000fd1</color>
+ <color name="i_am_color_fd2">#00000fd2</color>
+ <color name="i_am_color_fd3">#00000fd3</color>
+ <color name="i_am_color_fd4">#00000fd4</color>
+ <color name="i_am_color_fd5">#00000fd5</color>
+ <color name="i_am_color_fd6">#00000fd6</color>
+ <color name="i_am_color_fd7">#00000fd7</color>
+ <color name="i_am_color_fd8">#00000fd8</color>
+ <color name="i_am_color_fd9">#00000fd9</color>
+ <color name="i_am_color_fda">#00000fda</color>
+ <color name="i_am_color_fdb">#00000fdb</color>
+ <color name="i_am_color_fdc">#00000fdc</color>
+ <color name="i_am_color_fdd">#00000fdd</color>
+ <color name="i_am_color_fde">#00000fde</color>
+ <color name="i_am_color_fdf">#00000fdf</color>
+ <color name="i_am_color_fe0">#00000fe0</color>
+ <color name="i_am_color_fe1">#00000fe1</color>
+ <color name="i_am_color_fe2">#00000fe2</color>
+ <color name="i_am_color_fe3">#00000fe3</color>
+ <color name="i_am_color_fe4">#00000fe4</color>
+ <color name="i_am_color_fe5">#00000fe5</color>
+ <color name="i_am_color_fe6">#00000fe6</color>
+ <color name="i_am_color_fe7">#00000fe7</color>
+ <color name="i_am_color_fe8">#00000fe8</color>
+ <color name="i_am_color_fe9">#00000fe9</color>
+ <color name="i_am_color_fea">#00000fea</color>
+ <color name="i_am_color_feb">#00000feb</color>
+ <color name="i_am_color_fec">#00000fec</color>
+ <color name="i_am_color_fed">#00000fed</color>
+ <color name="i_am_color_fee">#00000fee</color>
+ <color name="i_am_color_fef">#00000fef</color>
+ <color name="i_am_color_ff0">#00000ff0</color>
+ <color name="i_am_color_ff1">#00000ff1</color>
+ <color name="i_am_color_ff2">#00000ff2</color>
+ <color name="i_am_color_ff3">#00000ff3</color>
+ <color name="i_am_color_ff4">#00000ff4</color>
+ <color name="i_am_color_ff5">#00000ff5</color>
+ <color name="i_am_color_ff6">#00000ff6</color>
+ <color name="i_am_color_ff7">#00000ff7</color>
+ <color name="i_am_color_ff8">#00000ff8</color>
+ <color name="i_am_color_ff9">#00000ff9</color>
+ <color name="i_am_color_ffa">#00000ffa</color>
+ <color name="i_am_color_ffb">#00000ffb</color>
+ <color name="i_am_color_ffc">#00000ffc</color>
+ <color name="i_am_color_ffd">#00000ffd</color>
+ <color name="i_am_color_ffe">#00000ffe</color>
+ <color name="i_am_color_fff">#00000fff</color>
+ <color name="i_am_color_1000">#00001000</color>
+ <color name="i_am_color_1001">#00001001</color>
+ <color name="i_am_color_1002">#00001002</color>
+ <color name="i_am_color_1003">#00001003</color>
+ <color name="i_am_color_1004">#00001004</color>
+ <color name="i_am_color_1005">#00001005</color>
+ <color name="i_am_color_1006">#00001006</color>
+ <color name="i_am_color_1007">#00001007</color>
+ <color name="i_am_color_1008">#00001008</color>
+ <color name="i_am_color_1009">#00001009</color>
+ <color name="i_am_color_100a">#0000100a</color>
+ <color name="i_am_color_100b">#0000100b</color>
+ <color name="i_am_color_100c">#0000100c</color>
+ <color name="i_am_color_100d">#0000100d</color>
+ <color name="i_am_color_100e">#0000100e</color>
+ <color name="i_am_color_100f">#0000100f</color>
+ <color name="i_am_color_1010">#00001010</color>
+ <color name="i_am_color_1011">#00001011</color>
+ <color name="i_am_color_1012">#00001012</color>
+ <color name="i_am_color_1013">#00001013</color>
+ <color name="i_am_color_1014">#00001014</color>
+ <color name="i_am_color_1015">#00001015</color>
+ <color name="i_am_color_1016">#00001016</color>
+ <color name="i_am_color_1017">#00001017</color>
+ <color name="i_am_color_1018">#00001018</color>
+ <color name="i_am_color_1019">#00001019</color>
+ <color name="i_am_color_101a">#0000101a</color>
+ <color name="i_am_color_101b">#0000101b</color>
+ <color name="i_am_color_101c">#0000101c</color>
+ <color name="i_am_color_101d">#0000101d</color>
+ <color name="i_am_color_101e">#0000101e</color>
+ <color name="i_am_color_101f">#0000101f</color>
+ <color name="i_am_color_1020">#00001020</color>
+ <color name="i_am_color_1021">#00001021</color>
+ <color name="i_am_color_1022">#00001022</color>
+ <color name="i_am_color_1023">#00001023</color>
+ <color name="i_am_color_1024">#00001024</color>
+ <color name="i_am_color_1025">#00001025</color>
+ <color name="i_am_color_1026">#00001026</color>
+ <color name="i_am_color_1027">#00001027</color>
+ <color name="i_am_color_1028">#00001028</color>
+ <color name="i_am_color_1029">#00001029</color>
+ <color name="i_am_color_102a">#0000102a</color>
+ <color name="i_am_color_102b">#0000102b</color>
+ <color name="i_am_color_102c">#0000102c</color>
+ <color name="i_am_color_102d">#0000102d</color>
+ <color name="i_am_color_102e">#0000102e</color>
+ <color name="i_am_color_102f">#0000102f</color>
+ <color name="i_am_color_1030">#00001030</color>
+ <color name="i_am_color_1031">#00001031</color>
+ <color name="i_am_color_1032">#00001032</color>
+ <color name="i_am_color_1033">#00001033</color>
+ <color name="i_am_color_1034">#00001034</color>
+ <color name="i_am_color_1035">#00001035</color>
+ <color name="i_am_color_1036">#00001036</color>
+ <color name="i_am_color_1037">#00001037</color>
+ <color name="i_am_color_1038">#00001038</color>
+ <color name="i_am_color_1039">#00001039</color>
+ <color name="i_am_color_103a">#0000103a</color>
+ <color name="i_am_color_103b">#0000103b</color>
+ <color name="i_am_color_103c">#0000103c</color>
+ <color name="i_am_color_103d">#0000103d</color>
+ <color name="i_am_color_103e">#0000103e</color>
+ <color name="i_am_color_103f">#0000103f</color>
+ <color name="i_am_color_1040">#00001040</color>
+ <color name="i_am_color_1041">#00001041</color>
+ <color name="i_am_color_1042">#00001042</color>
+ <color name="i_am_color_1043">#00001043</color>
+ <color name="i_am_color_1044">#00001044</color>
+ <color name="i_am_color_1045">#00001045</color>
+ <color name="i_am_color_1046">#00001046</color>
+ <color name="i_am_color_1047">#00001047</color>
+ <color name="i_am_color_1048">#00001048</color>
+ <color name="i_am_color_1049">#00001049</color>
+ <color name="i_am_color_104a">#0000104a</color>
+ <color name="i_am_color_104b">#0000104b</color>
+ <color name="i_am_color_104c">#0000104c</color>
+ <color name="i_am_color_104d">#0000104d</color>
+ <color name="i_am_color_104e">#0000104e</color>
+ <color name="i_am_color_104f">#0000104f</color>
+ <color name="i_am_color_1050">#00001050</color>
+ <color name="i_am_color_1051">#00001051</color>
+ <color name="i_am_color_1052">#00001052</color>
+ <color name="i_am_color_1053">#00001053</color>
+ <color name="i_am_color_1054">#00001054</color>
+ <color name="i_am_color_1055">#00001055</color>
+ <color name="i_am_color_1056">#00001056</color>
+ <color name="i_am_color_1057">#00001057</color>
+ <color name="i_am_color_1058">#00001058</color>
+ <color name="i_am_color_1059">#00001059</color>
+ <color name="i_am_color_105a">#0000105a</color>
+ <color name="i_am_color_105b">#0000105b</color>
+ <color name="i_am_color_105c">#0000105c</color>
+ <color name="i_am_color_105d">#0000105d</color>
+ <color name="i_am_color_105e">#0000105e</color>
+ <color name="i_am_color_105f">#0000105f</color>
+ <color name="i_am_color_1060">#00001060</color>
+ <color name="i_am_color_1061">#00001061</color>
+ <color name="i_am_color_1062">#00001062</color>
+ <color name="i_am_color_1063">#00001063</color>
+ <color name="i_am_color_1064">#00001064</color>
+ <color name="i_am_color_1065">#00001065</color>
+ <color name="i_am_color_1066">#00001066</color>
+ <color name="i_am_color_1067">#00001067</color>
+ <color name="i_am_color_1068">#00001068</color>
+ <color name="i_am_color_1069">#00001069</color>
+ <color name="i_am_color_106a">#0000106a</color>
+ <color name="i_am_color_106b">#0000106b</color>
+ <color name="i_am_color_106c">#0000106c</color>
+ <color name="i_am_color_106d">#0000106d</color>
+ <color name="i_am_color_106e">#0000106e</color>
+ <color name="i_am_color_106f">#0000106f</color>
+ <color name="i_am_color_1070">#00001070</color>
+ <color name="i_am_color_1071">#00001071</color>
+ <color name="i_am_color_1072">#00001072</color>
+ <color name="i_am_color_1073">#00001073</color>
+ <color name="i_am_color_1074">#00001074</color>
+ <color name="i_am_color_1075">#00001075</color>
+ <color name="i_am_color_1076">#00001076</color>
+ <color name="i_am_color_1077">#00001077</color>
+ <color name="i_am_color_1078">#00001078</color>
+ <color name="i_am_color_1079">#00001079</color>
+ <color name="i_am_color_107a">#0000107a</color>
+ <color name="i_am_color_107b">#0000107b</color>
+ <color name="i_am_color_107c">#0000107c</color>
+ <color name="i_am_color_107d">#0000107d</color>
+ <color name="i_am_color_107e">#0000107e</color>
+ <color name="i_am_color_107f">#0000107f</color>
+ <color name="i_am_color_1080">#00001080</color>
+ <color name="i_am_color_1081">#00001081</color>
+ <color name="i_am_color_1082">#00001082</color>
+ <color name="i_am_color_1083">#00001083</color>
+ <color name="i_am_color_1084">#00001084</color>
+ <color name="i_am_color_1085">#00001085</color>
+ <color name="i_am_color_1086">#00001086</color>
+ <color name="i_am_color_1087">#00001087</color>
+ <color name="i_am_color_1088">#00001088</color>
+ <color name="i_am_color_1089">#00001089</color>
+ <color name="i_am_color_108a">#0000108a</color>
+ <color name="i_am_color_108b">#0000108b</color>
+ <color name="i_am_color_108c">#0000108c</color>
+ <color name="i_am_color_108d">#0000108d</color>
+ <color name="i_am_color_108e">#0000108e</color>
+ <color name="i_am_color_108f">#0000108f</color>
+ <color name="i_am_color_1090">#00001090</color>
+ <color name="i_am_color_1091">#00001091</color>
+ <color name="i_am_color_1092">#00001092</color>
+ <color name="i_am_color_1093">#00001093</color>
+ <color name="i_am_color_1094">#00001094</color>
+ <color name="i_am_color_1095">#00001095</color>
+ <color name="i_am_color_1096">#00001096</color>
+ <color name="i_am_color_1097">#00001097</color>
+ <color name="i_am_color_1098">#00001098</color>
+ <color name="i_am_color_1099">#00001099</color>
+ <color name="i_am_color_109a">#0000109a</color>
+ <color name="i_am_color_109b">#0000109b</color>
+ <color name="i_am_color_109c">#0000109c</color>
+ <color name="i_am_color_109d">#0000109d</color>
+ <color name="i_am_color_109e">#0000109e</color>
+ <color name="i_am_color_109f">#0000109f</color>
+ <color name="i_am_color_10a0">#000010a0</color>
+ <color name="i_am_color_10a1">#000010a1</color>
+ <color name="i_am_color_10a2">#000010a2</color>
+ <color name="i_am_color_10a3">#000010a3</color>
+ <color name="i_am_color_10a4">#000010a4</color>
+ <color name="i_am_color_10a5">#000010a5</color>
+ <color name="i_am_color_10a6">#000010a6</color>
+ <color name="i_am_color_10a7">#000010a7</color>
+ <color name="i_am_color_10a8">#000010a8</color>
+ <color name="i_am_color_10a9">#000010a9</color>
+ <color name="i_am_color_10aa">#000010aa</color>
+ <color name="i_am_color_10ab">#000010ab</color>
+ <color name="i_am_color_10ac">#000010ac</color>
+ <color name="i_am_color_10ad">#000010ad</color>
+ <color name="i_am_color_10ae">#000010ae</color>
+ <color name="i_am_color_10af">#000010af</color>
+ <color name="i_am_color_10b0">#000010b0</color>
+ <color name="i_am_color_10b1">#000010b1</color>
+ <color name="i_am_color_10b2">#000010b2</color>
+ <color name="i_am_color_10b3">#000010b3</color>
+ <color name="i_am_color_10b4">#000010b4</color>
+ <color name="i_am_color_10b5">#000010b5</color>
+ <color name="i_am_color_10b6">#000010b6</color>
+ <color name="i_am_color_10b7">#000010b7</color>
+ <color name="i_am_color_10b8">#000010b8</color>
+ <color name="i_am_color_10b9">#000010b9</color>
+ <color name="i_am_color_10ba">#000010ba</color>
+ <color name="i_am_color_10bb">#000010bb</color>
+ <color name="i_am_color_10bc">#000010bc</color>
+ <color name="i_am_color_10bd">#000010bd</color>
+ <color name="i_am_color_10be">#000010be</color>
+ <color name="i_am_color_10bf">#000010bf</color>
+ <color name="i_am_color_10c0">#000010c0</color>
+ <color name="i_am_color_10c1">#000010c1</color>
+ <color name="i_am_color_10c2">#000010c2</color>
+ <color name="i_am_color_10c3">#000010c3</color>
+ <color name="i_am_color_10c4">#000010c4</color>
+ <color name="i_am_color_10c5">#000010c5</color>
+ <color name="i_am_color_10c6">#000010c6</color>
+ <color name="i_am_color_10c7">#000010c7</color>
+ <color name="i_am_color_10c8">#000010c8</color>
+ <color name="i_am_color_10c9">#000010c9</color>
+ <color name="i_am_color_10ca">#000010ca</color>
+ <color name="i_am_color_10cb">#000010cb</color>
+ <color name="i_am_color_10cc">#000010cc</color>
+ <color name="i_am_color_10cd">#000010cd</color>
+ <color name="i_am_color_10ce">#000010ce</color>
+ <color name="i_am_color_10cf">#000010cf</color>
+ <color name="i_am_color_10d0">#000010d0</color>
+ <color name="i_am_color_10d1">#000010d1</color>
+ <color name="i_am_color_10d2">#000010d2</color>
+ <color name="i_am_color_10d3">#000010d3</color>
+ <color name="i_am_color_10d4">#000010d4</color>
+ <color name="i_am_color_10d5">#000010d5</color>
+ <color name="i_am_color_10d6">#000010d6</color>
+ <color name="i_am_color_10d7">#000010d7</color>
+ <color name="i_am_color_10d8">#000010d8</color>
+ <color name="i_am_color_10d9">#000010d9</color>
+ <color name="i_am_color_10da">#000010da</color>
+ <color name="i_am_color_10db">#000010db</color>
+ <color name="i_am_color_10dc">#000010dc</color>
+ <color name="i_am_color_10dd">#000010dd</color>
+ <color name="i_am_color_10de">#000010de</color>
+ <color name="i_am_color_10df">#000010df</color>
+ <color name="i_am_color_10e0">#000010e0</color>
+ <color name="i_am_color_10e1">#000010e1</color>
+ <color name="i_am_color_10e2">#000010e2</color>
+ <color name="i_am_color_10e3">#000010e3</color>
+ <color name="i_am_color_10e4">#000010e4</color>
+ <color name="i_am_color_10e5">#000010e5</color>
+ <color name="i_am_color_10e6">#000010e6</color>
+ <color name="i_am_color_10e7">#000010e7</color>
+ <color name="i_am_color_10e8">#000010e8</color>
+ <color name="i_am_color_10e9">#000010e9</color>
+ <color name="i_am_color_10ea">#000010ea</color>
+ <color name="i_am_color_10eb">#000010eb</color>
+ <color name="i_am_color_10ec">#000010ec</color>
+ <color name="i_am_color_10ed">#000010ed</color>
+ <color name="i_am_color_10ee">#000010ee</color>
+ <color name="i_am_color_10ef">#000010ef</color>
+ <color name="i_am_color_10f0">#000010f0</color>
+ <color name="i_am_color_10f1">#000010f1</color>
+ <color name="i_am_color_10f2">#000010f2</color>
+ <color name="i_am_color_10f3">#000010f3</color>
+ <color name="i_am_color_10f4">#000010f4</color>
+ <color name="i_am_color_10f5">#000010f5</color>
+ <color name="i_am_color_10f6">#000010f6</color>
+ <color name="i_am_color_10f7">#000010f7</color>
+ <color name="i_am_color_10f8">#000010f8</color>
+ <color name="i_am_color_10f9">#000010f9</color>
+ <color name="i_am_color_10fa">#000010fa</color>
+ <color name="i_am_color_10fb">#000010fb</color>
+ <color name="i_am_color_10fc">#000010fc</color>
+ <color name="i_am_color_10fd">#000010fd</color>
+ <color name="i_am_color_10fe">#000010fe</color>
+ <color name="i_am_color_10ff">#000010ff</color>
+ <color name="i_am_color_1100">#00001100</color>
+ <color name="i_am_color_1101">#00001101</color>
+ <color name="i_am_color_1102">#00001102</color>
+ <color name="i_am_color_1103">#00001103</color>
+ <color name="i_am_color_1104">#00001104</color>
+ <color name="i_am_color_1105">#00001105</color>
+ <color name="i_am_color_1106">#00001106</color>
+ <color name="i_am_color_1107">#00001107</color>
+ <color name="i_am_color_1108">#00001108</color>
+ <color name="i_am_color_1109">#00001109</color>
+ <color name="i_am_color_110a">#0000110a</color>
+ <color name="i_am_color_110b">#0000110b</color>
+ <color name="i_am_color_110c">#0000110c</color>
+ <color name="i_am_color_110d">#0000110d</color>
+ <color name="i_am_color_110e">#0000110e</color>
+ <color name="i_am_color_110f">#0000110f</color>
+ <color name="i_am_color_1110">#00001110</color>
+ <color name="i_am_color_1111">#00001111</color>
+ <color name="i_am_color_1112">#00001112</color>
+ <color name="i_am_color_1113">#00001113</color>
+ <color name="i_am_color_1114">#00001114</color>
+ <color name="i_am_color_1115">#00001115</color>
+ <color name="i_am_color_1116">#00001116</color>
+ <color name="i_am_color_1117">#00001117</color>
+ <color name="i_am_color_1118">#00001118</color>
+ <color name="i_am_color_1119">#00001119</color>
+ <color name="i_am_color_111a">#0000111a</color>
+ <color name="i_am_color_111b">#0000111b</color>
+ <color name="i_am_color_111c">#0000111c</color>
+ <color name="i_am_color_111d">#0000111d</color>
+ <color name="i_am_color_111e">#0000111e</color>
+ <color name="i_am_color_111f">#0000111f</color>
+ <color name="i_am_color_1120">#00001120</color>
+ <color name="i_am_color_1121">#00001121</color>
+ <color name="i_am_color_1122">#00001122</color>
+ <color name="i_am_color_1123">#00001123</color>
+ <color name="i_am_color_1124">#00001124</color>
+ <color name="i_am_color_1125">#00001125</color>
+ <color name="i_am_color_1126">#00001126</color>
+ <color name="i_am_color_1127">#00001127</color>
+ <color name="i_am_color_1128">#00001128</color>
+ <color name="i_am_color_1129">#00001129</color>
+ <color name="i_am_color_112a">#0000112a</color>
+ <color name="i_am_color_112b">#0000112b</color>
+ <color name="i_am_color_112c">#0000112c</color>
+ <color name="i_am_color_112d">#0000112d</color>
+ <color name="i_am_color_112e">#0000112e</color>
+ <color name="i_am_color_112f">#0000112f</color>
+ <color name="i_am_color_1130">#00001130</color>
+ <color name="i_am_color_1131">#00001131</color>
+ <color name="i_am_color_1132">#00001132</color>
+ <color name="i_am_color_1133">#00001133</color>
+ <color name="i_am_color_1134">#00001134</color>
+ <color name="i_am_color_1135">#00001135</color>
+ <color name="i_am_color_1136">#00001136</color>
+ <color name="i_am_color_1137">#00001137</color>
+ <color name="i_am_color_1138">#00001138</color>
+ <color name="i_am_color_1139">#00001139</color>
+ <color name="i_am_color_113a">#0000113a</color>
+ <color name="i_am_color_113b">#0000113b</color>
+ <color name="i_am_color_113c">#0000113c</color>
+ <color name="i_am_color_113d">#0000113d</color>
+ <color name="i_am_color_113e">#0000113e</color>
+ <color name="i_am_color_113f">#0000113f</color>
+ <color name="i_am_color_1140">#00001140</color>
+ <color name="i_am_color_1141">#00001141</color>
+ <color name="i_am_color_1142">#00001142</color>
+ <color name="i_am_color_1143">#00001143</color>
+ <color name="i_am_color_1144">#00001144</color>
+ <color name="i_am_color_1145">#00001145</color>
+ <color name="i_am_color_1146">#00001146</color>
+ <color name="i_am_color_1147">#00001147</color>
+ <color name="i_am_color_1148">#00001148</color>
+ <color name="i_am_color_1149">#00001149</color>
+ <color name="i_am_color_114a">#0000114a</color>
+ <color name="i_am_color_114b">#0000114b</color>
+ <color name="i_am_color_114c">#0000114c</color>
+ <color name="i_am_color_114d">#0000114d</color>
+ <color name="i_am_color_114e">#0000114e</color>
+ <color name="i_am_color_114f">#0000114f</color>
+ <color name="i_am_color_1150">#00001150</color>
+ <color name="i_am_color_1151">#00001151</color>
+ <color name="i_am_color_1152">#00001152</color>
+ <color name="i_am_color_1153">#00001153</color>
+ <color name="i_am_color_1154">#00001154</color>
+ <color name="i_am_color_1155">#00001155</color>
+ <color name="i_am_color_1156">#00001156</color>
+ <color name="i_am_color_1157">#00001157</color>
+ <color name="i_am_color_1158">#00001158</color>
+ <color name="i_am_color_1159">#00001159</color>
+ <color name="i_am_color_115a">#0000115a</color>
+ <color name="i_am_color_115b">#0000115b</color>
+ <color name="i_am_color_115c">#0000115c</color>
+ <color name="i_am_color_115d">#0000115d</color>
+ <color name="i_am_color_115e">#0000115e</color>
+ <color name="i_am_color_115f">#0000115f</color>
+ <color name="i_am_color_1160">#00001160</color>
+ <color name="i_am_color_1161">#00001161</color>
+ <color name="i_am_color_1162">#00001162</color>
+ <color name="i_am_color_1163">#00001163</color>
+ <color name="i_am_color_1164">#00001164</color>
+ <color name="i_am_color_1165">#00001165</color>
+ <color name="i_am_color_1166">#00001166</color>
+ <color name="i_am_color_1167">#00001167</color>
+ <color name="i_am_color_1168">#00001168</color>
+ <color name="i_am_color_1169">#00001169</color>
+ <color name="i_am_color_116a">#0000116a</color>
+ <color name="i_am_color_116b">#0000116b</color>
+ <color name="i_am_color_116c">#0000116c</color>
+ <color name="i_am_color_116d">#0000116d</color>
+ <color name="i_am_color_116e">#0000116e</color>
+ <color name="i_am_color_116f">#0000116f</color>
+ <color name="i_am_color_1170">#00001170</color>
+ <color name="i_am_color_1171">#00001171</color>
+ <color name="i_am_color_1172">#00001172</color>
+ <color name="i_am_color_1173">#00001173</color>
+ <color name="i_am_color_1174">#00001174</color>
+ <color name="i_am_color_1175">#00001175</color>
+ <color name="i_am_color_1176">#00001176</color>
+ <color name="i_am_color_1177">#00001177</color>
+ <color name="i_am_color_1178">#00001178</color>
+ <color name="i_am_color_1179">#00001179</color>
+ <color name="i_am_color_117a">#0000117a</color>
+ <color name="i_am_color_117b">#0000117b</color>
+ <color name="i_am_color_117c">#0000117c</color>
+ <color name="i_am_color_117d">#0000117d</color>
+ <color name="i_am_color_117e">#0000117e</color>
+ <color name="i_am_color_117f">#0000117f</color>
+ <color name="i_am_color_1180">#00001180</color>
+ <color name="i_am_color_1181">#00001181</color>
+ <color name="i_am_color_1182">#00001182</color>
+ <color name="i_am_color_1183">#00001183</color>
+ <color name="i_am_color_1184">#00001184</color>
+ <color name="i_am_color_1185">#00001185</color>
+ <color name="i_am_color_1186">#00001186</color>
+ <color name="i_am_color_1187">#00001187</color>
+ <color name="i_am_color_1188">#00001188</color>
+ <color name="i_am_color_1189">#00001189</color>
+ <color name="i_am_color_118a">#0000118a</color>
+ <color name="i_am_color_118b">#0000118b</color>
+ <color name="i_am_color_118c">#0000118c</color>
+ <color name="i_am_color_118d">#0000118d</color>
+ <color name="i_am_color_118e">#0000118e</color>
+ <color name="i_am_color_118f">#0000118f</color>
+ <color name="i_am_color_1190">#00001190</color>
+ <color name="i_am_color_1191">#00001191</color>
+ <color name="i_am_color_1192">#00001192</color>
+ <color name="i_am_color_1193">#00001193</color>
+ <color name="i_am_color_1194">#00001194</color>
+ <color name="i_am_color_1195">#00001195</color>
+ <color name="i_am_color_1196">#00001196</color>
+ <color name="i_am_color_1197">#00001197</color>
+ <color name="i_am_color_1198">#00001198</color>
+ <color name="i_am_color_1199">#00001199</color>
+ <color name="i_am_color_119a">#0000119a</color>
+ <color name="i_am_color_119b">#0000119b</color>
+ <color name="i_am_color_119c">#0000119c</color>
+ <color name="i_am_color_119d">#0000119d</color>
+ <color name="i_am_color_119e">#0000119e</color>
+ <color name="i_am_color_119f">#0000119f</color>
+ <color name="i_am_color_11a0">#000011a0</color>
+ <color name="i_am_color_11a1">#000011a1</color>
+ <color name="i_am_color_11a2">#000011a2</color>
+ <color name="i_am_color_11a3">#000011a3</color>
+ <color name="i_am_color_11a4">#000011a4</color>
+ <color name="i_am_color_11a5">#000011a5</color>
+ <color name="i_am_color_11a6">#000011a6</color>
+ <color name="i_am_color_11a7">#000011a7</color>
+ <color name="i_am_color_11a8">#000011a8</color>
+ <color name="i_am_color_11a9">#000011a9</color>
+ <color name="i_am_color_11aa">#000011aa</color>
+ <color name="i_am_color_11ab">#000011ab</color>
+ <color name="i_am_color_11ac">#000011ac</color>
+ <color name="i_am_color_11ad">#000011ad</color>
+ <color name="i_am_color_11ae">#000011ae</color>
+ <color name="i_am_color_11af">#000011af</color>
+ <color name="i_am_color_11b0">#000011b0</color>
+ <color name="i_am_color_11b1">#000011b1</color>
+ <color name="i_am_color_11b2">#000011b2</color>
+ <color name="i_am_color_11b3">#000011b3</color>
+ <color name="i_am_color_11b4">#000011b4</color>
+ <color name="i_am_color_11b5">#000011b5</color>
+ <color name="i_am_color_11b6">#000011b6</color>
+ <color name="i_am_color_11b7">#000011b7</color>
+ <color name="i_am_color_11b8">#000011b8</color>
+ <color name="i_am_color_11b9">#000011b9</color>
+ <color name="i_am_color_11ba">#000011ba</color>
+ <color name="i_am_color_11bb">#000011bb</color>
+ <color name="i_am_color_11bc">#000011bc</color>
+ <color name="i_am_color_11bd">#000011bd</color>
+ <color name="i_am_color_11be">#000011be</color>
+ <color name="i_am_color_11bf">#000011bf</color>
+ <color name="i_am_color_11c0">#000011c0</color>
+ <color name="i_am_color_11c1">#000011c1</color>
+ <color name="i_am_color_11c2">#000011c2</color>
+ <color name="i_am_color_11c3">#000011c3</color>
+ <color name="i_am_color_11c4">#000011c4</color>
+ <color name="i_am_color_11c5">#000011c5</color>
+ <color name="i_am_color_11c6">#000011c6</color>
+ <color name="i_am_color_11c7">#000011c7</color>
+ <color name="i_am_color_11c8">#000011c8</color>
+ <color name="i_am_color_11c9">#000011c9</color>
+ <color name="i_am_color_11ca">#000011ca</color>
+ <color name="i_am_color_11cb">#000011cb</color>
+ <color name="i_am_color_11cc">#000011cc</color>
+ <color name="i_am_color_11cd">#000011cd</color>
+ <color name="i_am_color_11ce">#000011ce</color>
+ <color name="i_am_color_11cf">#000011cf</color>
+ <color name="i_am_color_11d0">#000011d0</color>
+ <color name="i_am_color_11d1">#000011d1</color>
+ <color name="i_am_color_11d2">#000011d2</color>
+ <color name="i_am_color_11d3">#000011d3</color>
+ <color name="i_am_color_11d4">#000011d4</color>
+ <color name="i_am_color_11d5">#000011d5</color>
+ <color name="i_am_color_11d6">#000011d6</color>
+ <color name="i_am_color_11d7">#000011d7</color>
+ <color name="i_am_color_11d8">#000011d8</color>
+ <color name="i_am_color_11d9">#000011d9</color>
+ <color name="i_am_color_11da">#000011da</color>
+ <color name="i_am_color_11db">#000011db</color>
+ <color name="i_am_color_11dc">#000011dc</color>
+ <color name="i_am_color_11dd">#000011dd</color>
+ <color name="i_am_color_11de">#000011de</color>
+ <color name="i_am_color_11df">#000011df</color>
+ <color name="i_am_color_11e0">#000011e0</color>
+ <color name="i_am_color_11e1">#000011e1</color>
+ <color name="i_am_color_11e2">#000011e2</color>
+ <color name="i_am_color_11e3">#000011e3</color>
+ <color name="i_am_color_11e4">#000011e4</color>
+ <color name="i_am_color_11e5">#000011e5</color>
+ <color name="i_am_color_11e6">#000011e6</color>
+ <color name="i_am_color_11e7">#000011e7</color>
+ <color name="i_am_color_11e8">#000011e8</color>
+ <color name="i_am_color_11e9">#000011e9</color>
+ <color name="i_am_color_11ea">#000011ea</color>
+ <color name="i_am_color_11eb">#000011eb</color>
+ <color name="i_am_color_11ec">#000011ec</color>
+ <color name="i_am_color_11ed">#000011ed</color>
+ <color name="i_am_color_11ee">#000011ee</color>
+ <color name="i_am_color_11ef">#000011ef</color>
+ <color name="i_am_color_11f0">#000011f0</color>
+ <color name="i_am_color_11f1">#000011f1</color>
+ <color name="i_am_color_11f2">#000011f2</color>
+ <color name="i_am_color_11f3">#000011f3</color>
+ <color name="i_am_color_11f4">#000011f4</color>
+ <color name="i_am_color_11f5">#000011f5</color>
+ <color name="i_am_color_11f6">#000011f6</color>
+ <color name="i_am_color_11f7">#000011f7</color>
+ <color name="i_am_color_11f8">#000011f8</color>
+ <color name="i_am_color_11f9">#000011f9</color>
+ <color name="i_am_color_11fa">#000011fa</color>
+ <color name="i_am_color_11fb">#000011fb</color>
+ <color name="i_am_color_11fc">#000011fc</color>
+ <color name="i_am_color_11fd">#000011fd</color>
+ <color name="i_am_color_11fe">#000011fe</color>
+ <color name="i_am_color_11ff">#000011ff</color>
+ <color name="i_am_color_1200">#00001200</color>
+ <color name="i_am_color_1201">#00001201</color>
+ <color name="i_am_color_1202">#00001202</color>
+ <color name="i_am_color_1203">#00001203</color>
+ <color name="i_am_color_1204">#00001204</color>
+ <color name="i_am_color_1205">#00001205</color>
+ <color name="i_am_color_1206">#00001206</color>
+ <color name="i_am_color_1207">#00001207</color>
+ <color name="i_am_color_1208">#00001208</color>
+ <color name="i_am_color_1209">#00001209</color>
+ <color name="i_am_color_120a">#0000120a</color>
+ <color name="i_am_color_120b">#0000120b</color>
+ <color name="i_am_color_120c">#0000120c</color>
+ <color name="i_am_color_120d">#0000120d</color>
+ <color name="i_am_color_120e">#0000120e</color>
+ <color name="i_am_color_120f">#0000120f</color>
+ <color name="i_am_color_1210">#00001210</color>
+ <color name="i_am_color_1211">#00001211</color>
+ <color name="i_am_color_1212">#00001212</color>
+ <color name="i_am_color_1213">#00001213</color>
+ <color name="i_am_color_1214">#00001214</color>
+ <color name="i_am_color_1215">#00001215</color>
+ <color name="i_am_color_1216">#00001216</color>
+ <color name="i_am_color_1217">#00001217</color>
+ <color name="i_am_color_1218">#00001218</color>
+ <color name="i_am_color_1219">#00001219</color>
+ <color name="i_am_color_121a">#0000121a</color>
+ <color name="i_am_color_121b">#0000121b</color>
+ <color name="i_am_color_121c">#0000121c</color>
+ <color name="i_am_color_121d">#0000121d</color>
+ <color name="i_am_color_121e">#0000121e</color>
+ <color name="i_am_color_121f">#0000121f</color>
+ <color name="i_am_color_1220">#00001220</color>
+ <color name="i_am_color_1221">#00001221</color>
+ <color name="i_am_color_1222">#00001222</color>
+ <color name="i_am_color_1223">#00001223</color>
+ <color name="i_am_color_1224">#00001224</color>
+ <color name="i_am_color_1225">#00001225</color>
+ <color name="i_am_color_1226">#00001226</color>
+ <color name="i_am_color_1227">#00001227</color>
+ <color name="i_am_color_1228">#00001228</color>
+ <color name="i_am_color_1229">#00001229</color>
+ <color name="i_am_color_122a">#0000122a</color>
+ <color name="i_am_color_122b">#0000122b</color>
+ <color name="i_am_color_122c">#0000122c</color>
+ <color name="i_am_color_122d">#0000122d</color>
+ <color name="i_am_color_122e">#0000122e</color>
+ <color name="i_am_color_122f">#0000122f</color>
+ <color name="i_am_color_1230">#00001230</color>
+ <color name="i_am_color_1231">#00001231</color>
+ <color name="i_am_color_1232">#00001232</color>
+ <color name="i_am_color_1233">#00001233</color>
+ <color name="i_am_color_1234">#00001234</color>
+ <color name="i_am_color_1235">#00001235</color>
+ <color name="i_am_color_1236">#00001236</color>
+ <color name="i_am_color_1237">#00001237</color>
+ <color name="i_am_color_1238">#00001238</color>
+ <color name="i_am_color_1239">#00001239</color>
+ <color name="i_am_color_123a">#0000123a</color>
+ <color name="i_am_color_123b">#0000123b</color>
+ <color name="i_am_color_123c">#0000123c</color>
+ <color name="i_am_color_123d">#0000123d</color>
+ <color name="i_am_color_123e">#0000123e</color>
+ <color name="i_am_color_123f">#0000123f</color>
+ <color name="i_am_color_1240">#00001240</color>
+ <color name="i_am_color_1241">#00001241</color>
+ <color name="i_am_color_1242">#00001242</color>
+ <color name="i_am_color_1243">#00001243</color>
+ <color name="i_am_color_1244">#00001244</color>
+ <color name="i_am_color_1245">#00001245</color>
+ <color name="i_am_color_1246">#00001246</color>
+ <color name="i_am_color_1247">#00001247</color>
+ <color name="i_am_color_1248">#00001248</color>
+ <color name="i_am_color_1249">#00001249</color>
+ <color name="i_am_color_124a">#0000124a</color>
+ <color name="i_am_color_124b">#0000124b</color>
+ <color name="i_am_color_124c">#0000124c</color>
+ <color name="i_am_color_124d">#0000124d</color>
+ <color name="i_am_color_124e">#0000124e</color>
+ <color name="i_am_color_124f">#0000124f</color>
+ <color name="i_am_color_1250">#00001250</color>
+ <color name="i_am_color_1251">#00001251</color>
+ <color name="i_am_color_1252">#00001252</color>
+ <color name="i_am_color_1253">#00001253</color>
+ <color name="i_am_color_1254">#00001254</color>
+ <color name="i_am_color_1255">#00001255</color>
+ <color name="i_am_color_1256">#00001256</color>
+ <color name="i_am_color_1257">#00001257</color>
+ <color name="i_am_color_1258">#00001258</color>
+ <color name="i_am_color_1259">#00001259</color>
+ <color name="i_am_color_125a">#0000125a</color>
+ <color name="i_am_color_125b">#0000125b</color>
+ <color name="i_am_color_125c">#0000125c</color>
+ <color name="i_am_color_125d">#0000125d</color>
+ <color name="i_am_color_125e">#0000125e</color>
+ <color name="i_am_color_125f">#0000125f</color>
+ <color name="i_am_color_1260">#00001260</color>
+ <color name="i_am_color_1261">#00001261</color>
+ <color name="i_am_color_1262">#00001262</color>
+ <color name="i_am_color_1263">#00001263</color>
+ <color name="i_am_color_1264">#00001264</color>
+ <color name="i_am_color_1265">#00001265</color>
+ <color name="i_am_color_1266">#00001266</color>
+ <color name="i_am_color_1267">#00001267</color>
+ <color name="i_am_color_1268">#00001268</color>
+ <color name="i_am_color_1269">#00001269</color>
+ <color name="i_am_color_126a">#0000126a</color>
+ <color name="i_am_color_126b">#0000126b</color>
+ <color name="i_am_color_126c">#0000126c</color>
+ <color name="i_am_color_126d">#0000126d</color>
+ <color name="i_am_color_126e">#0000126e</color>
+ <color name="i_am_color_126f">#0000126f</color>
+ <color name="i_am_color_1270">#00001270</color>
+ <color name="i_am_color_1271">#00001271</color>
+ <color name="i_am_color_1272">#00001272</color>
+ <color name="i_am_color_1273">#00001273</color>
+ <color name="i_am_color_1274">#00001274</color>
+ <color name="i_am_color_1275">#00001275</color>
+ <color name="i_am_color_1276">#00001276</color>
+ <color name="i_am_color_1277">#00001277</color>
+ <color name="i_am_color_1278">#00001278</color>
+ <color name="i_am_color_1279">#00001279</color>
+ <color name="i_am_color_127a">#0000127a</color>
+ <color name="i_am_color_127b">#0000127b</color>
+ <color name="i_am_color_127c">#0000127c</color>
+ <color name="i_am_color_127d">#0000127d</color>
+ <color name="i_am_color_127e">#0000127e</color>
+ <color name="i_am_color_127f">#0000127f</color>
+ <color name="i_am_color_1280">#00001280</color>
+ <color name="i_am_color_1281">#00001281</color>
+ <color name="i_am_color_1282">#00001282</color>
+ <color name="i_am_color_1283">#00001283</color>
+ <color name="i_am_color_1284">#00001284</color>
+ <color name="i_am_color_1285">#00001285</color>
+ <color name="i_am_color_1286">#00001286</color>
+ <color name="i_am_color_1287">#00001287</color>
+ <color name="i_am_color_1288">#00001288</color>
+ <color name="i_am_color_1289">#00001289</color>
+ <color name="i_am_color_128a">#0000128a</color>
+ <color name="i_am_color_128b">#0000128b</color>
+ <color name="i_am_color_128c">#0000128c</color>
+ <color name="i_am_color_128d">#0000128d</color>
+ <color name="i_am_color_128e">#0000128e</color>
+ <color name="i_am_color_128f">#0000128f</color>
+ <color name="i_am_color_1290">#00001290</color>
+ <color name="i_am_color_1291">#00001291</color>
+ <color name="i_am_color_1292">#00001292</color>
+ <color name="i_am_color_1293">#00001293</color>
+ <color name="i_am_color_1294">#00001294</color>
+ <color name="i_am_color_1295">#00001295</color>
+ <color name="i_am_color_1296">#00001296</color>
+ <color name="i_am_color_1297">#00001297</color>
+ <color name="i_am_color_1298">#00001298</color>
+ <color name="i_am_color_1299">#00001299</color>
+ <color name="i_am_color_129a">#0000129a</color>
+ <color name="i_am_color_129b">#0000129b</color>
+ <color name="i_am_color_129c">#0000129c</color>
+ <color name="i_am_color_129d">#0000129d</color>
+ <color name="i_am_color_129e">#0000129e</color>
+ <color name="i_am_color_129f">#0000129f</color>
+ <color name="i_am_color_12a0">#000012a0</color>
+ <color name="i_am_color_12a1">#000012a1</color>
+ <color name="i_am_color_12a2">#000012a2</color>
+ <color name="i_am_color_12a3">#000012a3</color>
+ <color name="i_am_color_12a4">#000012a4</color>
+ <color name="i_am_color_12a5">#000012a5</color>
+ <color name="i_am_color_12a6">#000012a6</color>
+ <color name="i_am_color_12a7">#000012a7</color>
+ <color name="i_am_color_12a8">#000012a8</color>
+ <color name="i_am_color_12a9">#000012a9</color>
+ <color name="i_am_color_12aa">#000012aa</color>
+ <color name="i_am_color_12ab">#000012ab</color>
+ <color name="i_am_color_12ac">#000012ac</color>
+ <color name="i_am_color_12ad">#000012ad</color>
+ <color name="i_am_color_12ae">#000012ae</color>
+ <color name="i_am_color_12af">#000012af</color>
+ <color name="i_am_color_12b0">#000012b0</color>
+ <color name="i_am_color_12b1">#000012b1</color>
+ <color name="i_am_color_12b2">#000012b2</color>
+ <color name="i_am_color_12b3">#000012b3</color>
+ <color name="i_am_color_12b4">#000012b4</color>
+ <color name="i_am_color_12b5">#000012b5</color>
+ <color name="i_am_color_12b6">#000012b6</color>
+ <color name="i_am_color_12b7">#000012b7</color>
+ <color name="i_am_color_12b8">#000012b8</color>
+ <color name="i_am_color_12b9">#000012b9</color>
+ <color name="i_am_color_12ba">#000012ba</color>
+ <color name="i_am_color_12bb">#000012bb</color>
+ <color name="i_am_color_12bc">#000012bc</color>
+ <color name="i_am_color_12bd">#000012bd</color>
+ <color name="i_am_color_12be">#000012be</color>
+ <color name="i_am_color_12bf">#000012bf</color>
+ <color name="i_am_color_12c0">#000012c0</color>
+ <color name="i_am_color_12c1">#000012c1</color>
+ <color name="i_am_color_12c2">#000012c2</color>
+ <color name="i_am_color_12c3">#000012c3</color>
+ <color name="i_am_color_12c4">#000012c4</color>
+ <color name="i_am_color_12c5">#000012c5</color>
+ <color name="i_am_color_12c6">#000012c6</color>
+ <color name="i_am_color_12c7">#000012c7</color>
+ <color name="i_am_color_12c8">#000012c8</color>
+ <color name="i_am_color_12c9">#000012c9</color>
+ <color name="i_am_color_12ca">#000012ca</color>
+ <color name="i_am_color_12cb">#000012cb</color>
+ <color name="i_am_color_12cc">#000012cc</color>
+ <color name="i_am_color_12cd">#000012cd</color>
+ <color name="i_am_color_12ce">#000012ce</color>
+ <color name="i_am_color_12cf">#000012cf</color>
+ <color name="i_am_color_12d0">#000012d0</color>
+ <color name="i_am_color_12d1">#000012d1</color>
+ <color name="i_am_color_12d2">#000012d2</color>
+ <color name="i_am_color_12d3">#000012d3</color>
+ <color name="i_am_color_12d4">#000012d4</color>
+ <color name="i_am_color_12d5">#000012d5</color>
+ <color name="i_am_color_12d6">#000012d6</color>
+ <color name="i_am_color_12d7">#000012d7</color>
+ <color name="i_am_color_12d8">#000012d8</color>
+ <color name="i_am_color_12d9">#000012d9</color>
+ <color name="i_am_color_12da">#000012da</color>
+ <color name="i_am_color_12db">#000012db</color>
+ <color name="i_am_color_12dc">#000012dc</color>
+ <color name="i_am_color_12dd">#000012dd</color>
+ <color name="i_am_color_12de">#000012de</color>
+ <color name="i_am_color_12df">#000012df</color>
+ <color name="i_am_color_12e0">#000012e0</color>
+ <color name="i_am_color_12e1">#000012e1</color>
+ <color name="i_am_color_12e2">#000012e2</color>
+ <color name="i_am_color_12e3">#000012e3</color>
+ <color name="i_am_color_12e4">#000012e4</color>
+ <color name="i_am_color_12e5">#000012e5</color>
+ <color name="i_am_color_12e6">#000012e6</color>
+ <color name="i_am_color_12e7">#000012e7</color>
+ <color name="i_am_color_12e8">#000012e8</color>
+ <color name="i_am_color_12e9">#000012e9</color>
+ <color name="i_am_color_12ea">#000012ea</color>
+ <color name="i_am_color_12eb">#000012eb</color>
+ <color name="i_am_color_12ec">#000012ec</color>
+ <color name="i_am_color_12ed">#000012ed</color>
+ <color name="i_am_color_12ee">#000012ee</color>
+ <color name="i_am_color_12ef">#000012ef</color>
+ <color name="i_am_color_12f0">#000012f0</color>
+ <color name="i_am_color_12f1">#000012f1</color>
+ <color name="i_am_color_12f2">#000012f2</color>
+ <color name="i_am_color_12f3">#000012f3</color>
+ <color name="i_am_color_12f4">#000012f4</color>
+ <color name="i_am_color_12f5">#000012f5</color>
+ <color name="i_am_color_12f6">#000012f6</color>
+ <color name="i_am_color_12f7">#000012f7</color>
+ <color name="i_am_color_12f8">#000012f8</color>
+ <color name="i_am_color_12f9">#000012f9</color>
+ <color name="i_am_color_12fa">#000012fa</color>
+ <color name="i_am_color_12fb">#000012fb</color>
+ <color name="i_am_color_12fc">#000012fc</color>
+ <color name="i_am_color_12fd">#000012fd</color>
+ <color name="i_am_color_12fe">#000012fe</color>
+ <color name="i_am_color_12ff">#000012ff</color>
+ <color name="i_am_color_1300">#00001300</color>
+ <color name="i_am_color_1301">#00001301</color>
+ <color name="i_am_color_1302">#00001302</color>
+ <color name="i_am_color_1303">#00001303</color>
+ <color name="i_am_color_1304">#00001304</color>
+ <color name="i_am_color_1305">#00001305</color>
+ <color name="i_am_color_1306">#00001306</color>
+ <color name="i_am_color_1307">#00001307</color>
+ <color name="i_am_color_1308">#00001308</color>
+ <color name="i_am_color_1309">#00001309</color>
+ <color name="i_am_color_130a">#0000130a</color>
+ <color name="i_am_color_130b">#0000130b</color>
+ <color name="i_am_color_130c">#0000130c</color>
+ <color name="i_am_color_130d">#0000130d</color>
+ <color name="i_am_color_130e">#0000130e</color>
+ <color name="i_am_color_130f">#0000130f</color>
+ <color name="i_am_color_1310">#00001310</color>
+ <color name="i_am_color_1311">#00001311</color>
+ <color name="i_am_color_1312">#00001312</color>
+ <color name="i_am_color_1313">#00001313</color>
+ <color name="i_am_color_1314">#00001314</color>
+ <color name="i_am_color_1315">#00001315</color>
+ <color name="i_am_color_1316">#00001316</color>
+ <color name="i_am_color_1317">#00001317</color>
+ <color name="i_am_color_1318">#00001318</color>
+ <color name="i_am_color_1319">#00001319</color>
+ <color name="i_am_color_131a">#0000131a</color>
+ <color name="i_am_color_131b">#0000131b</color>
+ <color name="i_am_color_131c">#0000131c</color>
+ <color name="i_am_color_131d">#0000131d</color>
+ <color name="i_am_color_131e">#0000131e</color>
+ <color name="i_am_color_131f">#0000131f</color>
+ <color name="i_am_color_1320">#00001320</color>
+ <color name="i_am_color_1321">#00001321</color>
+ <color name="i_am_color_1322">#00001322</color>
+ <color name="i_am_color_1323">#00001323</color>
+ <color name="i_am_color_1324">#00001324</color>
+ <color name="i_am_color_1325">#00001325</color>
+ <color name="i_am_color_1326">#00001326</color>
+ <color name="i_am_color_1327">#00001327</color>
+ <color name="i_am_color_1328">#00001328</color>
+ <color name="i_am_color_1329">#00001329</color>
+ <color name="i_am_color_132a">#0000132a</color>
+ <color name="i_am_color_132b">#0000132b</color>
+ <color name="i_am_color_132c">#0000132c</color>
+ <color name="i_am_color_132d">#0000132d</color>
+ <color name="i_am_color_132e">#0000132e</color>
+ <color name="i_am_color_132f">#0000132f</color>
+ <color name="i_am_color_1330">#00001330</color>
+ <color name="i_am_color_1331">#00001331</color>
+ <color name="i_am_color_1332">#00001332</color>
+ <color name="i_am_color_1333">#00001333</color>
+ <color name="i_am_color_1334">#00001334</color>
+ <color name="i_am_color_1335">#00001335</color>
+ <color name="i_am_color_1336">#00001336</color>
+ <color name="i_am_color_1337">#00001337</color>
+ <color name="i_am_color_1338">#00001338</color>
+ <color name="i_am_color_1339">#00001339</color>
+ <color name="i_am_color_133a">#0000133a</color>
+ <color name="i_am_color_133b">#0000133b</color>
+ <color name="i_am_color_133c">#0000133c</color>
+ <color name="i_am_color_133d">#0000133d</color>
+ <color name="i_am_color_133e">#0000133e</color>
+ <color name="i_am_color_133f">#0000133f</color>
+ <color name="i_am_color_1340">#00001340</color>
+ <color name="i_am_color_1341">#00001341</color>
+ <color name="i_am_color_1342">#00001342</color>
+ <color name="i_am_color_1343">#00001343</color>
+ <color name="i_am_color_1344">#00001344</color>
+ <color name="i_am_color_1345">#00001345</color>
+ <color name="i_am_color_1346">#00001346</color>
+ <color name="i_am_color_1347">#00001347</color>
+ <color name="i_am_color_1348">#00001348</color>
+ <color name="i_am_color_1349">#00001349</color>
+ <color name="i_am_color_134a">#0000134a</color>
+ <color name="i_am_color_134b">#0000134b</color>
+ <color name="i_am_color_134c">#0000134c</color>
+ <color name="i_am_color_134d">#0000134d</color>
+ <color name="i_am_color_134e">#0000134e</color>
+ <color name="i_am_color_134f">#0000134f</color>
+ <color name="i_am_color_1350">#00001350</color>
+ <color name="i_am_color_1351">#00001351</color>
+ <color name="i_am_color_1352">#00001352</color>
+ <color name="i_am_color_1353">#00001353</color>
+ <color name="i_am_color_1354">#00001354</color>
+ <color name="i_am_color_1355">#00001355</color>
+ <color name="i_am_color_1356">#00001356</color>
+ <color name="i_am_color_1357">#00001357</color>
+ <color name="i_am_color_1358">#00001358</color>
+ <color name="i_am_color_1359">#00001359</color>
+ <color name="i_am_color_135a">#0000135a</color>
+ <color name="i_am_color_135b">#0000135b</color>
+ <color name="i_am_color_135c">#0000135c</color>
+ <color name="i_am_color_135d">#0000135d</color>
+ <color name="i_am_color_135e">#0000135e</color>
+ <color name="i_am_color_135f">#0000135f</color>
+ <color name="i_am_color_1360">#00001360</color>
+ <color name="i_am_color_1361">#00001361</color>
+ <color name="i_am_color_1362">#00001362</color>
+ <color name="i_am_color_1363">#00001363</color>
+ <color name="i_am_color_1364">#00001364</color>
+ <color name="i_am_color_1365">#00001365</color>
+ <color name="i_am_color_1366">#00001366</color>
+ <color name="i_am_color_1367">#00001367</color>
+ <color name="i_am_color_1368">#00001368</color>
+ <color name="i_am_color_1369">#00001369</color>
+ <color name="i_am_color_136a">#0000136a</color>
+ <color name="i_am_color_136b">#0000136b</color>
+ <color name="i_am_color_136c">#0000136c</color>
+ <color name="i_am_color_136d">#0000136d</color>
+ <color name="i_am_color_136e">#0000136e</color>
+ <color name="i_am_color_136f">#0000136f</color>
+ <color name="i_am_color_1370">#00001370</color>
+ <color name="i_am_color_1371">#00001371</color>
+ <color name="i_am_color_1372">#00001372</color>
+ <color name="i_am_color_1373">#00001373</color>
+ <color name="i_am_color_1374">#00001374</color>
+ <color name="i_am_color_1375">#00001375</color>
+ <color name="i_am_color_1376">#00001376</color>
+ <color name="i_am_color_1377">#00001377</color>
+ <color name="i_am_color_1378">#00001378</color>
+ <color name="i_am_color_1379">#00001379</color>
+ <color name="i_am_color_137a">#0000137a</color>
+ <color name="i_am_color_137b">#0000137b</color>
+ <color name="i_am_color_137c">#0000137c</color>
+ <color name="i_am_color_137d">#0000137d</color>
+ <color name="i_am_color_137e">#0000137e</color>
+ <color name="i_am_color_137f">#0000137f</color>
+ <color name="i_am_color_1380">#00001380</color>
+ <color name="i_am_color_1381">#00001381</color>
+ <color name="i_am_color_1382">#00001382</color>
+ <color name="i_am_color_1383">#00001383</color>
+ <color name="i_am_color_1384">#00001384</color>
+ <color name="i_am_color_1385">#00001385</color>
+ <color name="i_am_color_1386">#00001386</color>
+ <color name="i_am_color_1387">#00001387</color>
+ <color name="i_am_color_1388">#00001388</color>
+ <color name="i_am_color_1389">#00001389</color>
+ <color name="i_am_color_138a">#0000138a</color>
+ <color name="i_am_color_138b">#0000138b</color>
+ <color name="i_am_color_138c">#0000138c</color>
+ <color name="i_am_color_138d">#0000138d</color>
+ <color name="i_am_color_138e">#0000138e</color>
+ <color name="i_am_color_138f">#0000138f</color>
+ <color name="i_am_color_1390">#00001390</color>
+ <color name="i_am_color_1391">#00001391</color>
+ <color name="i_am_color_1392">#00001392</color>
+ <color name="i_am_color_1393">#00001393</color>
+ <color name="i_am_color_1394">#00001394</color>
+ <color name="i_am_color_1395">#00001395</color>
+ <color name="i_am_color_1396">#00001396</color>
+ <color name="i_am_color_1397">#00001397</color>
+ <color name="i_am_color_1398">#00001398</color>
+ <color name="i_am_color_1399">#00001399</color>
+ <color name="i_am_color_139a">#0000139a</color>
+ <color name="i_am_color_139b">#0000139b</color>
+ <color name="i_am_color_139c">#0000139c</color>
+ <color name="i_am_color_139d">#0000139d</color>
+ <color name="i_am_color_139e">#0000139e</color>
+ <color name="i_am_color_139f">#0000139f</color>
+ <color name="i_am_color_13a0">#000013a0</color>
+ <color name="i_am_color_13a1">#000013a1</color>
+ <color name="i_am_color_13a2">#000013a2</color>
+ <color name="i_am_color_13a3">#000013a3</color>
+ <color name="i_am_color_13a4">#000013a4</color>
+ <color name="i_am_color_13a5">#000013a5</color>
+ <color name="i_am_color_13a6">#000013a6</color>
+ <color name="i_am_color_13a7">#000013a7</color>
+ <color name="i_am_color_13a8">#000013a8</color>
+ <color name="i_am_color_13a9">#000013a9</color>
+ <color name="i_am_color_13aa">#000013aa</color>
+ <color name="i_am_color_13ab">#000013ab</color>
+ <color name="i_am_color_13ac">#000013ac</color>
+ <color name="i_am_color_13ad">#000013ad</color>
+ <color name="i_am_color_13ae">#000013ae</color>
+ <color name="i_am_color_13af">#000013af</color>
+ <color name="i_am_color_13b0">#000013b0</color>
+ <color name="i_am_color_13b1">#000013b1</color>
+ <color name="i_am_color_13b2">#000013b2</color>
+ <color name="i_am_color_13b3">#000013b3</color>
+ <color name="i_am_color_13b4">#000013b4</color>
+ <color name="i_am_color_13b5">#000013b5</color>
+ <color name="i_am_color_13b6">#000013b6</color>
+ <color name="i_am_color_13b7">#000013b7</color>
+ <color name="i_am_color_13b8">#000013b8</color>
+ <color name="i_am_color_13b9">#000013b9</color>
+ <color name="i_am_color_13ba">#000013ba</color>
+ <color name="i_am_color_13bb">#000013bb</color>
+ <color name="i_am_color_13bc">#000013bc</color>
+ <color name="i_am_color_13bd">#000013bd</color>
+ <color name="i_am_color_13be">#000013be</color>
+ <color name="i_am_color_13bf">#000013bf</color>
+ <color name="i_am_color_13c0">#000013c0</color>
+ <color name="i_am_color_13c1">#000013c1</color>
+ <color name="i_am_color_13c2">#000013c2</color>
+ <color name="i_am_color_13c3">#000013c3</color>
+ <color name="i_am_color_13c4">#000013c4</color>
+ <color name="i_am_color_13c5">#000013c5</color>
+ <color name="i_am_color_13c6">#000013c6</color>
+ <color name="i_am_color_13c7">#000013c7</color>
+ <color name="i_am_color_13c8">#000013c8</color>
+ <color name="i_am_color_13c9">#000013c9</color>
+ <color name="i_am_color_13ca">#000013ca</color>
+ <color name="i_am_color_13cb">#000013cb</color>
+ <color name="i_am_color_13cc">#000013cc</color>
+ <color name="i_am_color_13cd">#000013cd</color>
+ <color name="i_am_color_13ce">#000013ce</color>
+ <color name="i_am_color_13cf">#000013cf</color>
+ <color name="i_am_color_13d0">#000013d0</color>
+ <color name="i_am_color_13d1">#000013d1</color>
+ <color name="i_am_color_13d2">#000013d2</color>
+ <color name="i_am_color_13d3">#000013d3</color>
+ <color name="i_am_color_13d4">#000013d4</color>
+ <color name="i_am_color_13d5">#000013d5</color>
+ <color name="i_am_color_13d6">#000013d6</color>
+ <color name="i_am_color_13d7">#000013d7</color>
+ <color name="i_am_color_13d8">#000013d8</color>
+ <color name="i_am_color_13d9">#000013d9</color>
+ <color name="i_am_color_13da">#000013da</color>
+ <color name="i_am_color_13db">#000013db</color>
+ <color name="i_am_color_13dc">#000013dc</color>
+ <color name="i_am_color_13dd">#000013dd</color>
+ <color name="i_am_color_13de">#000013de</color>
+ <color name="i_am_color_13df">#000013df</color>
+ <color name="i_am_color_13e0">#000013e0</color>
+ <color name="i_am_color_13e1">#000013e1</color>
+ <color name="i_am_color_13e2">#000013e2</color>
+ <color name="i_am_color_13e3">#000013e3</color>
+ <color name="i_am_color_13e4">#000013e4</color>
+ <color name="i_am_color_13e5">#000013e5</color>
+ <color name="i_am_color_13e6">#000013e6</color>
+ <color name="i_am_color_13e7">#000013e7</color>
+ <color name="i_am_color_13e8">#000013e8</color>
+ <color name="i_am_color_13e9">#000013e9</color>
+ <color name="i_am_color_13ea">#000013ea</color>
+ <color name="i_am_color_13eb">#000013eb</color>
+ <color name="i_am_color_13ec">#000013ec</color>
+ <color name="i_am_color_13ed">#000013ed</color>
+ <color name="i_am_color_13ee">#000013ee</color>
+ <color name="i_am_color_13ef">#000013ef</color>
+ <color name="i_am_color_13f0">#000013f0</color>
+ <color name="i_am_color_13f1">#000013f1</color>
+ <color name="i_am_color_13f2">#000013f2</color>
+ <color name="i_am_color_13f3">#000013f3</color>
+ <color name="i_am_color_13f4">#000013f4</color>
+ <color name="i_am_color_13f5">#000013f5</color>
+ <color name="i_am_color_13f6">#000013f6</color>
+ <color name="i_am_color_13f7">#000013f7</color>
+ <color name="i_am_color_13f8">#000013f8</color>
+ <color name="i_am_color_13f9">#000013f9</color>
+ <color name="i_am_color_13fa">#000013fa</color>
+ <color name="i_am_color_13fb">#000013fb</color>
+ <color name="i_am_color_13fc">#000013fc</color>
+ <color name="i_am_color_13fd">#000013fd</color>
+ <color name="i_am_color_13fe">#000013fe</color>
+ <color name="i_am_color_13ff">#000013ff</color>
+ <color name="i_am_color_1400">#00001400</color>
+ <color name="i_am_color_1401">#00001401</color>
+ <color name="i_am_color_1402">#00001402</color>
+ <color name="i_am_color_1403">#00001403</color>
+ <color name="i_am_color_1404">#00001404</color>
+ <color name="i_am_color_1405">#00001405</color>
+ <color name="i_am_color_1406">#00001406</color>
+ <color name="i_am_color_1407">#00001407</color>
+ <color name="i_am_color_1408">#00001408</color>
+ <color name="i_am_color_1409">#00001409</color>
+ <color name="i_am_color_140a">#0000140a</color>
+ <color name="i_am_color_140b">#0000140b</color>
+ <color name="i_am_color_140c">#0000140c</color>
+ <color name="i_am_color_140d">#0000140d</color>
+ <color name="i_am_color_140e">#0000140e</color>
+ <color name="i_am_color_140f">#0000140f</color>
+ <color name="i_am_color_1410">#00001410</color>
+ <color name="i_am_color_1411">#00001411</color>
+ <color name="i_am_color_1412">#00001412</color>
+ <color name="i_am_color_1413">#00001413</color>
+ <color name="i_am_color_1414">#00001414</color>
+ <color name="i_am_color_1415">#00001415</color>
+ <color name="i_am_color_1416">#00001416</color>
+ <color name="i_am_color_1417">#00001417</color>
+ <color name="i_am_color_1418">#00001418</color>
+ <color name="i_am_color_1419">#00001419</color>
+ <color name="i_am_color_141a">#0000141a</color>
+ <color name="i_am_color_141b">#0000141b</color>
+ <color name="i_am_color_141c">#0000141c</color>
+ <color name="i_am_color_141d">#0000141d</color>
+ <color name="i_am_color_141e">#0000141e</color>
+ <color name="i_am_color_141f">#0000141f</color>
+ <color name="i_am_color_1420">#00001420</color>
+ <color name="i_am_color_1421">#00001421</color>
+ <color name="i_am_color_1422">#00001422</color>
+ <color name="i_am_color_1423">#00001423</color>
+ <color name="i_am_color_1424">#00001424</color>
+ <color name="i_am_color_1425">#00001425</color>
+ <color name="i_am_color_1426">#00001426</color>
+ <color name="i_am_color_1427">#00001427</color>
+ <color name="i_am_color_1428">#00001428</color>
+ <color name="i_am_color_1429">#00001429</color>
+ <color name="i_am_color_142a">#0000142a</color>
+ <color name="i_am_color_142b">#0000142b</color>
+ <color name="i_am_color_142c">#0000142c</color>
+ <color name="i_am_color_142d">#0000142d</color>
+ <color name="i_am_color_142e">#0000142e</color>
+ <color name="i_am_color_142f">#0000142f</color>
+ <color name="i_am_color_1430">#00001430</color>
+ <color name="i_am_color_1431">#00001431</color>
+ <color name="i_am_color_1432">#00001432</color>
+ <color name="i_am_color_1433">#00001433</color>
+ <color name="i_am_color_1434">#00001434</color>
+ <color name="i_am_color_1435">#00001435</color>
+ <color name="i_am_color_1436">#00001436</color>
+ <color name="i_am_color_1437">#00001437</color>
+ <color name="i_am_color_1438">#00001438</color>
+ <color name="i_am_color_1439">#00001439</color>
+ <color name="i_am_color_143a">#0000143a</color>
+ <color name="i_am_color_143b">#0000143b</color>
+ <color name="i_am_color_143c">#0000143c</color>
+ <color name="i_am_color_143d">#0000143d</color>
+ <color name="i_am_color_143e">#0000143e</color>
+ <color name="i_am_color_143f">#0000143f</color>
+ <color name="i_am_color_1440">#00001440</color>
+ <color name="i_am_color_1441">#00001441</color>
+ <color name="i_am_color_1442">#00001442</color>
+ <color name="i_am_color_1443">#00001443</color>
+ <color name="i_am_color_1444">#00001444</color>
+ <color name="i_am_color_1445">#00001445</color>
+ <color name="i_am_color_1446">#00001446</color>
+ <color name="i_am_color_1447">#00001447</color>
+ <color name="i_am_color_1448">#00001448</color>
+ <color name="i_am_color_1449">#00001449</color>
+ <color name="i_am_color_144a">#0000144a</color>
+ <color name="i_am_color_144b">#0000144b</color>
+ <color name="i_am_color_144c">#0000144c</color>
+ <color name="i_am_color_144d">#0000144d</color>
+ <color name="i_am_color_144e">#0000144e</color>
+ <color name="i_am_color_144f">#0000144f</color>
+ <color name="i_am_color_1450">#00001450</color>
+ <color name="i_am_color_1451">#00001451</color>
+ <color name="i_am_color_1452">#00001452</color>
+ <color name="i_am_color_1453">#00001453</color>
+ <color name="i_am_color_1454">#00001454</color>
+ <color name="i_am_color_1455">#00001455</color>
+ <color name="i_am_color_1456">#00001456</color>
+ <color name="i_am_color_1457">#00001457</color>
+ <color name="i_am_color_1458">#00001458</color>
+ <color name="i_am_color_1459">#00001459</color>
+ <color name="i_am_color_145a">#0000145a</color>
+ <color name="i_am_color_145b">#0000145b</color>
+ <color name="i_am_color_145c">#0000145c</color>
+ <color name="i_am_color_145d">#0000145d</color>
+ <color name="i_am_color_145e">#0000145e</color>
+ <color name="i_am_color_145f">#0000145f</color>
+ <color name="i_am_color_1460">#00001460</color>
+ <color name="i_am_color_1461">#00001461</color>
+ <color name="i_am_color_1462">#00001462</color>
+ <color name="i_am_color_1463">#00001463</color>
+ <color name="i_am_color_1464">#00001464</color>
+ <color name="i_am_color_1465">#00001465</color>
+ <color name="i_am_color_1466">#00001466</color>
+ <color name="i_am_color_1467">#00001467</color>
+ <color name="i_am_color_1468">#00001468</color>
+ <color name="i_am_color_1469">#00001469</color>
+ <color name="i_am_color_146a">#0000146a</color>
+ <color name="i_am_color_146b">#0000146b</color>
+ <color name="i_am_color_146c">#0000146c</color>
+ <color name="i_am_color_146d">#0000146d</color>
+ <color name="i_am_color_146e">#0000146e</color>
+ <color name="i_am_color_146f">#0000146f</color>
+ <color name="i_am_color_1470">#00001470</color>
+ <color name="i_am_color_1471">#00001471</color>
+ <color name="i_am_color_1472">#00001472</color>
+ <color name="i_am_color_1473">#00001473</color>
+ <color name="i_am_color_1474">#00001474</color>
+ <color name="i_am_color_1475">#00001475</color>
+ <color name="i_am_color_1476">#00001476</color>
+ <color name="i_am_color_1477">#00001477</color>
+ <color name="i_am_color_1478">#00001478</color>
+ <color name="i_am_color_1479">#00001479</color>
+ <color name="i_am_color_147a">#0000147a</color>
+ <color name="i_am_color_147b">#0000147b</color>
+ <color name="i_am_color_147c">#0000147c</color>
+ <color name="i_am_color_147d">#0000147d</color>
+ <color name="i_am_color_147e">#0000147e</color>
+ <color name="i_am_color_147f">#0000147f</color>
+ <color name="i_am_color_1480">#00001480</color>
+ <color name="i_am_color_1481">#00001481</color>
+ <color name="i_am_color_1482">#00001482</color>
+ <color name="i_am_color_1483">#00001483</color>
+ <color name="i_am_color_1484">#00001484</color>
+ <color name="i_am_color_1485">#00001485</color>
+ <color name="i_am_color_1486">#00001486</color>
+ <color name="i_am_color_1487">#00001487</color>
+ <color name="i_am_color_1488">#00001488</color>
+ <color name="i_am_color_1489">#00001489</color>
+ <color name="i_am_color_148a">#0000148a</color>
+ <color name="i_am_color_148b">#0000148b</color>
+ <color name="i_am_color_148c">#0000148c</color>
+ <color name="i_am_color_148d">#0000148d</color>
+ <color name="i_am_color_148e">#0000148e</color>
+ <color name="i_am_color_148f">#0000148f</color>
+ <color name="i_am_color_1490">#00001490</color>
+ <color name="i_am_color_1491">#00001491</color>
+ <color name="i_am_color_1492">#00001492</color>
+ <color name="i_am_color_1493">#00001493</color>
+ <color name="i_am_color_1494">#00001494</color>
+ <color name="i_am_color_1495">#00001495</color>
+ <color name="i_am_color_1496">#00001496</color>
+ <color name="i_am_color_1497">#00001497</color>
+ <color name="i_am_color_1498">#00001498</color>
+ <color name="i_am_color_1499">#00001499</color>
+ <color name="i_am_color_149a">#0000149a</color>
+ <color name="i_am_color_149b">#0000149b</color>
+ <color name="i_am_color_149c">#0000149c</color>
+ <color name="i_am_color_149d">#0000149d</color>
+ <color name="i_am_color_149e">#0000149e</color>
+ <color name="i_am_color_149f">#0000149f</color>
+ <color name="i_am_color_14a0">#000014a0</color>
+ <color name="i_am_color_14a1">#000014a1</color>
+ <color name="i_am_color_14a2">#000014a2</color>
+ <color name="i_am_color_14a3">#000014a3</color>
+ <color name="i_am_color_14a4">#000014a4</color>
+ <color name="i_am_color_14a5">#000014a5</color>
+ <color name="i_am_color_14a6">#000014a6</color>
+ <color name="i_am_color_14a7">#000014a7</color>
+ <color name="i_am_color_14a8">#000014a8</color>
+ <color name="i_am_color_14a9">#000014a9</color>
+ <color name="i_am_color_14aa">#000014aa</color>
+ <color name="i_am_color_14ab">#000014ab</color>
+ <color name="i_am_color_14ac">#000014ac</color>
+ <color name="i_am_color_14ad">#000014ad</color>
+ <color name="i_am_color_14ae">#000014ae</color>
+ <color name="i_am_color_14af">#000014af</color>
+ <color name="i_am_color_14b0">#000014b0</color>
+ <color name="i_am_color_14b1">#000014b1</color>
+ <color name="i_am_color_14b2">#000014b2</color>
+ <color name="i_am_color_14b3">#000014b3</color>
+ <color name="i_am_color_14b4">#000014b4</color>
+ <color name="i_am_color_14b5">#000014b5</color>
+ <color name="i_am_color_14b6">#000014b6</color>
+ <color name="i_am_color_14b7">#000014b7</color>
+ <color name="i_am_color_14b8">#000014b8</color>
+ <color name="i_am_color_14b9">#000014b9</color>
+ <color name="i_am_color_14ba">#000014ba</color>
+ <color name="i_am_color_14bb">#000014bb</color>
+ <color name="i_am_color_14bc">#000014bc</color>
+ <color name="i_am_color_14bd">#000014bd</color>
+ <color name="i_am_color_14be">#000014be</color>
+ <color name="i_am_color_14bf">#000014bf</color>
+ <color name="i_am_color_14c0">#000014c0</color>
+ <color name="i_am_color_14c1">#000014c1</color>
+ <color name="i_am_color_14c2">#000014c2</color>
+ <color name="i_am_color_14c3">#000014c3</color>
+ <color name="i_am_color_14c4">#000014c4</color>
+ <color name="i_am_color_14c5">#000014c5</color>
+ <color name="i_am_color_14c6">#000014c6</color>
+ <color name="i_am_color_14c7">#000014c7</color>
+ <color name="i_am_color_14c8">#000014c8</color>
+ <color name="i_am_color_14c9">#000014c9</color>
+ <color name="i_am_color_14ca">#000014ca</color>
+ <color name="i_am_color_14cb">#000014cb</color>
+ <color name="i_am_color_14cc">#000014cc</color>
+ <color name="i_am_color_14cd">#000014cd</color>
+ <color name="i_am_color_14ce">#000014ce</color>
+ <color name="i_am_color_14cf">#000014cf</color>
+ <color name="i_am_color_14d0">#000014d0</color>
+ <color name="i_am_color_14d1">#000014d1</color>
+ <color name="i_am_color_14d2">#000014d2</color>
+ <color name="i_am_color_14d3">#000014d3</color>
+ <color name="i_am_color_14d4">#000014d4</color>
+ <color name="i_am_color_14d5">#000014d5</color>
+ <color name="i_am_color_14d6">#000014d6</color>
+ <color name="i_am_color_14d7">#000014d7</color>
+ <color name="i_am_color_14d8">#000014d8</color>
+ <color name="i_am_color_14d9">#000014d9</color>
+ <color name="i_am_color_14da">#000014da</color>
+ <color name="i_am_color_14db">#000014db</color>
+ <color name="i_am_color_14dc">#000014dc</color>
+ <color name="i_am_color_14dd">#000014dd</color>
+ <color name="i_am_color_14de">#000014de</color>
+ <color name="i_am_color_14df">#000014df</color>
+ <color name="i_am_color_14e0">#000014e0</color>
+ <color name="i_am_color_14e1">#000014e1</color>
+ <color name="i_am_color_14e2">#000014e2</color>
+ <color name="i_am_color_14e3">#000014e3</color>
+ <color name="i_am_color_14e4">#000014e4</color>
+ <color name="i_am_color_14e5">#000014e5</color>
+ <color name="i_am_color_14e6">#000014e6</color>
+ <color name="i_am_color_14e7">#000014e7</color>
+ <color name="i_am_color_14e8">#000014e8</color>
+ <color name="i_am_color_14e9">#000014e9</color>
+ <color name="i_am_color_14ea">#000014ea</color>
+ <color name="i_am_color_14eb">#000014eb</color>
+ <color name="i_am_color_14ec">#000014ec</color>
+ <color name="i_am_color_14ed">#000014ed</color>
+ <color name="i_am_color_14ee">#000014ee</color>
+ <color name="i_am_color_14ef">#000014ef</color>
+ <color name="i_am_color_14f0">#000014f0</color>
+ <color name="i_am_color_14f1">#000014f1</color>
+ <color name="i_am_color_14f2">#000014f2</color>
+ <color name="i_am_color_14f3">#000014f3</color>
+ <color name="i_am_color_14f4">#000014f4</color>
+ <color name="i_am_color_14f5">#000014f5</color>
+ <color name="i_am_color_14f6">#000014f6</color>
+ <color name="i_am_color_14f7">#000014f7</color>
+ <color name="i_am_color_14f8">#000014f8</color>
+ <color name="i_am_color_14f9">#000014f9</color>
+ <color name="i_am_color_14fa">#000014fa</color>
+ <color name="i_am_color_14fb">#000014fb</color>
+ <color name="i_am_color_14fc">#000014fc</color>
+ <color name="i_am_color_14fd">#000014fd</color>
+ <color name="i_am_color_14fe">#000014fe</color>
+ <color name="i_am_color_14ff">#000014ff</color>
+ <color name="i_am_color_1500">#00001500</color>
+ <color name="i_am_color_1501">#00001501</color>
+ <color name="i_am_color_1502">#00001502</color>
+ <color name="i_am_color_1503">#00001503</color>
+ <color name="i_am_color_1504">#00001504</color>
+ <color name="i_am_color_1505">#00001505</color>
+ <color name="i_am_color_1506">#00001506</color>
+ <color name="i_am_color_1507">#00001507</color>
+ <color name="i_am_color_1508">#00001508</color>
+ <color name="i_am_color_1509">#00001509</color>
+ <color name="i_am_color_150a">#0000150a</color>
+ <color name="i_am_color_150b">#0000150b</color>
+ <color name="i_am_color_150c">#0000150c</color>
+ <color name="i_am_color_150d">#0000150d</color>
+ <color name="i_am_color_150e">#0000150e</color>
+ <color name="i_am_color_150f">#0000150f</color>
+ <color name="i_am_color_1510">#00001510</color>
+ <color name="i_am_color_1511">#00001511</color>
+ <color name="i_am_color_1512">#00001512</color>
+ <color name="i_am_color_1513">#00001513</color>
+ <color name="i_am_color_1514">#00001514</color>
+ <color name="i_am_color_1515">#00001515</color>
+ <color name="i_am_color_1516">#00001516</color>
+ <color name="i_am_color_1517">#00001517</color>
+ <color name="i_am_color_1518">#00001518</color>
+ <color name="i_am_color_1519">#00001519</color>
+ <color name="i_am_color_151a">#0000151a</color>
+ <color name="i_am_color_151b">#0000151b</color>
+ <color name="i_am_color_151c">#0000151c</color>
+ <color name="i_am_color_151d">#0000151d</color>
+ <color name="i_am_color_151e">#0000151e</color>
+ <color name="i_am_color_151f">#0000151f</color>
+ <color name="i_am_color_1520">#00001520</color>
+ <color name="i_am_color_1521">#00001521</color>
+ <color name="i_am_color_1522">#00001522</color>
+ <color name="i_am_color_1523">#00001523</color>
+ <color name="i_am_color_1524">#00001524</color>
+ <color name="i_am_color_1525">#00001525</color>
+ <color name="i_am_color_1526">#00001526</color>
+ <color name="i_am_color_1527">#00001527</color>
+ <color name="i_am_color_1528">#00001528</color>
+ <color name="i_am_color_1529">#00001529</color>
+ <color name="i_am_color_152a">#0000152a</color>
+ <color name="i_am_color_152b">#0000152b</color>
+ <color name="i_am_color_152c">#0000152c</color>
+ <color name="i_am_color_152d">#0000152d</color>
+ <color name="i_am_color_152e">#0000152e</color>
+ <color name="i_am_color_152f">#0000152f</color>
+ <color name="i_am_color_1530">#00001530</color>
+ <color name="i_am_color_1531">#00001531</color>
+ <color name="i_am_color_1532">#00001532</color>
+ <color name="i_am_color_1533">#00001533</color>
+ <color name="i_am_color_1534">#00001534</color>
+ <color name="i_am_color_1535">#00001535</color>
+ <color name="i_am_color_1536">#00001536</color>
+ <color name="i_am_color_1537">#00001537</color>
+ <color name="i_am_color_1538">#00001538</color>
+ <color name="i_am_color_1539">#00001539</color>
+ <color name="i_am_color_153a">#0000153a</color>
+ <color name="i_am_color_153b">#0000153b</color>
+ <color name="i_am_color_153c">#0000153c</color>
+ <color name="i_am_color_153d">#0000153d</color>
+ <color name="i_am_color_153e">#0000153e</color>
+ <color name="i_am_color_153f">#0000153f</color>
+ <color name="i_am_color_1540">#00001540</color>
+ <color name="i_am_color_1541">#00001541</color>
+ <color name="i_am_color_1542">#00001542</color>
+ <color name="i_am_color_1543">#00001543</color>
+ <color name="i_am_color_1544">#00001544</color>
+ <color name="i_am_color_1545">#00001545</color>
+ <color name="i_am_color_1546">#00001546</color>
+ <color name="i_am_color_1547">#00001547</color>
+ <color name="i_am_color_1548">#00001548</color>
+ <color name="i_am_color_1549">#00001549</color>
+ <color name="i_am_color_154a">#0000154a</color>
+ <color name="i_am_color_154b">#0000154b</color>
+ <color name="i_am_color_154c">#0000154c</color>
+ <color name="i_am_color_154d">#0000154d</color>
+ <color name="i_am_color_154e">#0000154e</color>
+ <color name="i_am_color_154f">#0000154f</color>
+ <color name="i_am_color_1550">#00001550</color>
+ <color name="i_am_color_1551">#00001551</color>
+ <color name="i_am_color_1552">#00001552</color>
+ <color name="i_am_color_1553">#00001553</color>
+ <color name="i_am_color_1554">#00001554</color>
+ <color name="i_am_color_1555">#00001555</color>
+ <color name="i_am_color_1556">#00001556</color>
+ <color name="i_am_color_1557">#00001557</color>
+ <color name="i_am_color_1558">#00001558</color>
+ <color name="i_am_color_1559">#00001559</color>
+ <color name="i_am_color_155a">#0000155a</color>
+ <color name="i_am_color_155b">#0000155b</color>
+ <color name="i_am_color_155c">#0000155c</color>
+ <color name="i_am_color_155d">#0000155d</color>
+ <color name="i_am_color_155e">#0000155e</color>
+ <color name="i_am_color_155f">#0000155f</color>
+ <color name="i_am_color_1560">#00001560</color>
+ <color name="i_am_color_1561">#00001561</color>
+ <color name="i_am_color_1562">#00001562</color>
+ <color name="i_am_color_1563">#00001563</color>
+ <color name="i_am_color_1564">#00001564</color>
+ <color name="i_am_color_1565">#00001565</color>
+ <color name="i_am_color_1566">#00001566</color>
+ <color name="i_am_color_1567">#00001567</color>
+ <color name="i_am_color_1568">#00001568</color>
+ <color name="i_am_color_1569">#00001569</color>
+ <color name="i_am_color_156a">#0000156a</color>
+ <color name="i_am_color_156b">#0000156b</color>
+ <color name="i_am_color_156c">#0000156c</color>
+ <color name="i_am_color_156d">#0000156d</color>
+ <color name="i_am_color_156e">#0000156e</color>
+ <color name="i_am_color_156f">#0000156f</color>
+ <color name="i_am_color_1570">#00001570</color>
+ <color name="i_am_color_1571">#00001571</color>
+ <color name="i_am_color_1572">#00001572</color>
+ <color name="i_am_color_1573">#00001573</color>
+ <color name="i_am_color_1574">#00001574</color>
+ <color name="i_am_color_1575">#00001575</color>
+ <color name="i_am_color_1576">#00001576</color>
+ <color name="i_am_color_1577">#00001577</color>
+ <color name="i_am_color_1578">#00001578</color>
+ <color name="i_am_color_1579">#00001579</color>
+ <color name="i_am_color_157a">#0000157a</color>
+ <color name="i_am_color_157b">#0000157b</color>
+ <color name="i_am_color_157c">#0000157c</color>
+ <color name="i_am_color_157d">#0000157d</color>
+ <color name="i_am_color_157e">#0000157e</color>
+ <color name="i_am_color_157f">#0000157f</color>
+ <color name="i_am_color_1580">#00001580</color>
+ <color name="i_am_color_1581">#00001581</color>
+ <color name="i_am_color_1582">#00001582</color>
+ <color name="i_am_color_1583">#00001583</color>
+ <color name="i_am_color_1584">#00001584</color>
+ <color name="i_am_color_1585">#00001585</color>
+ <color name="i_am_color_1586">#00001586</color>
+ <color name="i_am_color_1587">#00001587</color>
+ <color name="i_am_color_1588">#00001588</color>
+ <color name="i_am_color_1589">#00001589</color>
+ <color name="i_am_color_158a">#0000158a</color>
+ <color name="i_am_color_158b">#0000158b</color>
+ <color name="i_am_color_158c">#0000158c</color>
+ <color name="i_am_color_158d">#0000158d</color>
+ <color name="i_am_color_158e">#0000158e</color>
+ <color name="i_am_color_158f">#0000158f</color>
+ <color name="i_am_color_1590">#00001590</color>
+ <color name="i_am_color_1591">#00001591</color>
+ <color name="i_am_color_1592">#00001592</color>
+ <color name="i_am_color_1593">#00001593</color>
+ <color name="i_am_color_1594">#00001594</color>
+ <color name="i_am_color_1595">#00001595</color>
+ <color name="i_am_color_1596">#00001596</color>
+ <color name="i_am_color_1597">#00001597</color>
+ <color name="i_am_color_1598">#00001598</color>
+ <color name="i_am_color_1599">#00001599</color>
+ <color name="i_am_color_159a">#0000159a</color>
+ <color name="i_am_color_159b">#0000159b</color>
+ <color name="i_am_color_159c">#0000159c</color>
+ <color name="i_am_color_159d">#0000159d</color>
+ <color name="i_am_color_159e">#0000159e</color>
+ <color name="i_am_color_159f">#0000159f</color>
+ <color name="i_am_color_15a0">#000015a0</color>
+ <color name="i_am_color_15a1">#000015a1</color>
+ <color name="i_am_color_15a2">#000015a2</color>
+ <color name="i_am_color_15a3">#000015a3</color>
+ <color name="i_am_color_15a4">#000015a4</color>
+ <color name="i_am_color_15a5">#000015a5</color>
+ <color name="i_am_color_15a6">#000015a6</color>
+ <color name="i_am_color_15a7">#000015a7</color>
+ <color name="i_am_color_15a8">#000015a8</color>
+ <color name="i_am_color_15a9">#000015a9</color>
+ <color name="i_am_color_15aa">#000015aa</color>
+ <color name="i_am_color_15ab">#000015ab</color>
+ <color name="i_am_color_15ac">#000015ac</color>
+ <color name="i_am_color_15ad">#000015ad</color>
+ <color name="i_am_color_15ae">#000015ae</color>
+ <color name="i_am_color_15af">#000015af</color>
+ <color name="i_am_color_15b0">#000015b0</color>
+ <color name="i_am_color_15b1">#000015b1</color>
+ <color name="i_am_color_15b2">#000015b2</color>
+ <color name="i_am_color_15b3">#000015b3</color>
+ <color name="i_am_color_15b4">#000015b4</color>
+ <color name="i_am_color_15b5">#000015b5</color>
+ <color name="i_am_color_15b6">#000015b6</color>
+ <color name="i_am_color_15b7">#000015b7</color>
+ <color name="i_am_color_15b8">#000015b8</color>
+ <color name="i_am_color_15b9">#000015b9</color>
+ <color name="i_am_color_15ba">#000015ba</color>
+ <color name="i_am_color_15bb">#000015bb</color>
+ <color name="i_am_color_15bc">#000015bc</color>
+ <color name="i_am_color_15bd">#000015bd</color>
+ <color name="i_am_color_15be">#000015be</color>
+ <color name="i_am_color_15bf">#000015bf</color>
+ <color name="i_am_color_15c0">#000015c0</color>
+ <color name="i_am_color_15c1">#000015c1</color>
+ <color name="i_am_color_15c2">#000015c2</color>
+ <color name="i_am_color_15c3">#000015c3</color>
+ <color name="i_am_color_15c4">#000015c4</color>
+ <color name="i_am_color_15c5">#000015c5</color>
+ <color name="i_am_color_15c6">#000015c6</color>
+ <color name="i_am_color_15c7">#000015c7</color>
+ <color name="i_am_color_15c8">#000015c8</color>
+ <color name="i_am_color_15c9">#000015c9</color>
+ <color name="i_am_color_15ca">#000015ca</color>
+ <color name="i_am_color_15cb">#000015cb</color>
+ <color name="i_am_color_15cc">#000015cc</color>
+ <color name="i_am_color_15cd">#000015cd</color>
+ <color name="i_am_color_15ce">#000015ce</color>
+ <color name="i_am_color_15cf">#000015cf</color>
+ <color name="i_am_color_15d0">#000015d0</color>
+ <color name="i_am_color_15d1">#000015d1</color>
+ <color name="i_am_color_15d2">#000015d2</color>
+ <color name="i_am_color_15d3">#000015d3</color>
+ <color name="i_am_color_15d4">#000015d4</color>
+ <color name="i_am_color_15d5">#000015d5</color>
+ <color name="i_am_color_15d6">#000015d6</color>
+ <color name="i_am_color_15d7">#000015d7</color>
+ <color name="i_am_color_15d8">#000015d8</color>
+ <color name="i_am_color_15d9">#000015d9</color>
+ <color name="i_am_color_15da">#000015da</color>
+ <color name="i_am_color_15db">#000015db</color>
+ <color name="i_am_color_15dc">#000015dc</color>
+ <color name="i_am_color_15dd">#000015dd</color>
+ <color name="i_am_color_15de">#000015de</color>
+ <color name="i_am_color_15df">#000015df</color>
+ <color name="i_am_color_15e0">#000015e0</color>
+ <color name="i_am_color_15e1">#000015e1</color>
+ <color name="i_am_color_15e2">#000015e2</color>
+ <color name="i_am_color_15e3">#000015e3</color>
+ <color name="i_am_color_15e4">#000015e4</color>
+ <color name="i_am_color_15e5">#000015e5</color>
+ <color name="i_am_color_15e6">#000015e6</color>
+ <color name="i_am_color_15e7">#000015e7</color>
+ <color name="i_am_color_15e8">#000015e8</color>
+ <color name="i_am_color_15e9">#000015e9</color>
+ <color name="i_am_color_15ea">#000015ea</color>
+ <color name="i_am_color_15eb">#000015eb</color>
+ <color name="i_am_color_15ec">#000015ec</color>
+ <color name="i_am_color_15ed">#000015ed</color>
+ <color name="i_am_color_15ee">#000015ee</color>
+ <color name="i_am_color_15ef">#000015ef</color>
+ <color name="i_am_color_15f0">#000015f0</color>
+ <color name="i_am_color_15f1">#000015f1</color>
+ <color name="i_am_color_15f2">#000015f2</color>
+ <color name="i_am_color_15f3">#000015f3</color>
+ <color name="i_am_color_15f4">#000015f4</color>
+ <color name="i_am_color_15f5">#000015f5</color>
+ <color name="i_am_color_15f6">#000015f6</color>
+ <color name="i_am_color_15f7">#000015f7</color>
+ <color name="i_am_color_15f8">#000015f8</color>
+ <color name="i_am_color_15f9">#000015f9</color>
+ <color name="i_am_color_15fa">#000015fa</color>
+ <color name="i_am_color_15fb">#000015fb</color>
+ <color name="i_am_color_15fc">#000015fc</color>
+ <color name="i_am_color_15fd">#000015fd</color>
+ <color name="i_am_color_15fe">#000015fe</color>
+ <color name="i_am_color_15ff">#000015ff</color>
+ <color name="i_am_color_1600">#00001600</color>
+ <color name="i_am_color_1601">#00001601</color>
+ <color name="i_am_color_1602">#00001602</color>
+ <color name="i_am_color_1603">#00001603</color>
+ <color name="i_am_color_1604">#00001604</color>
+ <color name="i_am_color_1605">#00001605</color>
+ <color name="i_am_color_1606">#00001606</color>
+ <color name="i_am_color_1607">#00001607</color>
+ <color name="i_am_color_1608">#00001608</color>
+ <color name="i_am_color_1609">#00001609</color>
+ <color name="i_am_color_160a">#0000160a</color>
+ <color name="i_am_color_160b">#0000160b</color>
+ <color name="i_am_color_160c">#0000160c</color>
+ <color name="i_am_color_160d">#0000160d</color>
+ <color name="i_am_color_160e">#0000160e</color>
+ <color name="i_am_color_160f">#0000160f</color>
+ <color name="i_am_color_1610">#00001610</color>
+ <color name="i_am_color_1611">#00001611</color>
+ <color name="i_am_color_1612">#00001612</color>
+ <color name="i_am_color_1613">#00001613</color>
+ <color name="i_am_color_1614">#00001614</color>
+ <color name="i_am_color_1615">#00001615</color>
+ <color name="i_am_color_1616">#00001616</color>
+ <color name="i_am_color_1617">#00001617</color>
+ <color name="i_am_color_1618">#00001618</color>
+ <color name="i_am_color_1619">#00001619</color>
+ <color name="i_am_color_161a">#0000161a</color>
+ <color name="i_am_color_161b">#0000161b</color>
+ <color name="i_am_color_161c">#0000161c</color>
+ <color name="i_am_color_161d">#0000161d</color>
+ <color name="i_am_color_161e">#0000161e</color>
+ <color name="i_am_color_161f">#0000161f</color>
+ <color name="i_am_color_1620">#00001620</color>
+ <color name="i_am_color_1621">#00001621</color>
+ <color name="i_am_color_1622">#00001622</color>
+ <color name="i_am_color_1623">#00001623</color>
+ <color name="i_am_color_1624">#00001624</color>
+ <color name="i_am_color_1625">#00001625</color>
+ <color name="i_am_color_1626">#00001626</color>
+ <color name="i_am_color_1627">#00001627</color>
+ <color name="i_am_color_1628">#00001628</color>
+ <color name="i_am_color_1629">#00001629</color>
+ <color name="i_am_color_162a">#0000162a</color>
+ <color name="i_am_color_162b">#0000162b</color>
+ <color name="i_am_color_162c">#0000162c</color>
+ <color name="i_am_color_162d">#0000162d</color>
+ <color name="i_am_color_162e">#0000162e</color>
+ <color name="i_am_color_162f">#0000162f</color>
+ <color name="i_am_color_1630">#00001630</color>
+ <color name="i_am_color_1631">#00001631</color>
+ <color name="i_am_color_1632">#00001632</color>
+ <color name="i_am_color_1633">#00001633</color>
+ <color name="i_am_color_1634">#00001634</color>
+ <color name="i_am_color_1635">#00001635</color>
+ <color name="i_am_color_1636">#00001636</color>
+ <color name="i_am_color_1637">#00001637</color>
+ <color name="i_am_color_1638">#00001638</color>
+ <color name="i_am_color_1639">#00001639</color>
+ <color name="i_am_color_163a">#0000163a</color>
+ <color name="i_am_color_163b">#0000163b</color>
+ <color name="i_am_color_163c">#0000163c</color>
+ <color name="i_am_color_163d">#0000163d</color>
+ <color name="i_am_color_163e">#0000163e</color>
+ <color name="i_am_color_163f">#0000163f</color>
+ <color name="i_am_color_1640">#00001640</color>
+ <color name="i_am_color_1641">#00001641</color>
+ <color name="i_am_color_1642">#00001642</color>
+ <color name="i_am_color_1643">#00001643</color>
+ <color name="i_am_color_1644">#00001644</color>
+ <color name="i_am_color_1645">#00001645</color>
+ <color name="i_am_color_1646">#00001646</color>
+ <color name="i_am_color_1647">#00001647</color>
+ <color name="i_am_color_1648">#00001648</color>
+ <color name="i_am_color_1649">#00001649</color>
+ <color name="i_am_color_164a">#0000164a</color>
+ <color name="i_am_color_164b">#0000164b</color>
+ <color name="i_am_color_164c">#0000164c</color>
+ <color name="i_am_color_164d">#0000164d</color>
+ <color name="i_am_color_164e">#0000164e</color>
+ <color name="i_am_color_164f">#0000164f</color>
+ <color name="i_am_color_1650">#00001650</color>
+ <color name="i_am_color_1651">#00001651</color>
+ <color name="i_am_color_1652">#00001652</color>
+ <color name="i_am_color_1653">#00001653</color>
+ <color name="i_am_color_1654">#00001654</color>
+ <color name="i_am_color_1655">#00001655</color>
+ <color name="i_am_color_1656">#00001656</color>
+ <color name="i_am_color_1657">#00001657</color>
+ <color name="i_am_color_1658">#00001658</color>
+ <color name="i_am_color_1659">#00001659</color>
+ <color name="i_am_color_165a">#0000165a</color>
+ <color name="i_am_color_165b">#0000165b</color>
+ <color name="i_am_color_165c">#0000165c</color>
+ <color name="i_am_color_165d">#0000165d</color>
+ <color name="i_am_color_165e">#0000165e</color>
+ <color name="i_am_color_165f">#0000165f</color>
+ <color name="i_am_color_1660">#00001660</color>
+ <color name="i_am_color_1661">#00001661</color>
+ <color name="i_am_color_1662">#00001662</color>
+ <color name="i_am_color_1663">#00001663</color>
+ <color name="i_am_color_1664">#00001664</color>
+ <color name="i_am_color_1665">#00001665</color>
+ <color name="i_am_color_1666">#00001666</color>
+ <color name="i_am_color_1667">#00001667</color>
+ <color name="i_am_color_1668">#00001668</color>
+ <color name="i_am_color_1669">#00001669</color>
+ <color name="i_am_color_166a">#0000166a</color>
+ <color name="i_am_color_166b">#0000166b</color>
+ <color name="i_am_color_166c">#0000166c</color>
+ <color name="i_am_color_166d">#0000166d</color>
+ <color name="i_am_color_166e">#0000166e</color>
+ <color name="i_am_color_166f">#0000166f</color>
+ <color name="i_am_color_1670">#00001670</color>
+ <color name="i_am_color_1671">#00001671</color>
+ <color name="i_am_color_1672">#00001672</color>
+ <color name="i_am_color_1673">#00001673</color>
+ <color name="i_am_color_1674">#00001674</color>
+ <color name="i_am_color_1675">#00001675</color>
+ <color name="i_am_color_1676">#00001676</color>
+ <color name="i_am_color_1677">#00001677</color>
+ <color name="i_am_color_1678">#00001678</color>
+ <color name="i_am_color_1679">#00001679</color>
+ <color name="i_am_color_167a">#0000167a</color>
+ <color name="i_am_color_167b">#0000167b</color>
+ <color name="i_am_color_167c">#0000167c</color>
+ <color name="i_am_color_167d">#0000167d</color>
+ <color name="i_am_color_167e">#0000167e</color>
+ <color name="i_am_color_167f">#0000167f</color>
+ <color name="i_am_color_1680">#00001680</color>
+ <color name="i_am_color_1681">#00001681</color>
+ <color name="i_am_color_1682">#00001682</color>
+ <color name="i_am_color_1683">#00001683</color>
+ <color name="i_am_color_1684">#00001684</color>
+ <color name="i_am_color_1685">#00001685</color>
+ <color name="i_am_color_1686">#00001686</color>
+ <color name="i_am_color_1687">#00001687</color>
+ <color name="i_am_color_1688">#00001688</color>
+ <color name="i_am_color_1689">#00001689</color>
+ <color name="i_am_color_168a">#0000168a</color>
+ <color name="i_am_color_168b">#0000168b</color>
+ <color name="i_am_color_168c">#0000168c</color>
+ <color name="i_am_color_168d">#0000168d</color>
+ <color name="i_am_color_168e">#0000168e</color>
+ <color name="i_am_color_168f">#0000168f</color>
+ <color name="i_am_color_1690">#00001690</color>
+ <color name="i_am_color_1691">#00001691</color>
+ <color name="i_am_color_1692">#00001692</color>
+ <color name="i_am_color_1693">#00001693</color>
+ <color name="i_am_color_1694">#00001694</color>
+ <color name="i_am_color_1695">#00001695</color>
+ <color name="i_am_color_1696">#00001696</color>
+ <color name="i_am_color_1697">#00001697</color>
+ <color name="i_am_color_1698">#00001698</color>
+ <color name="i_am_color_1699">#00001699</color>
+ <color name="i_am_color_169a">#0000169a</color>
+ <color name="i_am_color_169b">#0000169b</color>
+ <color name="i_am_color_169c">#0000169c</color>
+ <color name="i_am_color_169d">#0000169d</color>
+ <color name="i_am_color_169e">#0000169e</color>
+ <color name="i_am_color_169f">#0000169f</color>
+ <color name="i_am_color_16a0">#000016a0</color>
+ <color name="i_am_color_16a1">#000016a1</color>
+ <color name="i_am_color_16a2">#000016a2</color>
+ <color name="i_am_color_16a3">#000016a3</color>
+ <color name="i_am_color_16a4">#000016a4</color>
+ <color name="i_am_color_16a5">#000016a5</color>
+ <color name="i_am_color_16a6">#000016a6</color>
+ <color name="i_am_color_16a7">#000016a7</color>
+ <color name="i_am_color_16a8">#000016a8</color>
+ <color name="i_am_color_16a9">#000016a9</color>
+ <color name="i_am_color_16aa">#000016aa</color>
+ <color name="i_am_color_16ab">#000016ab</color>
+ <color name="i_am_color_16ac">#000016ac</color>
+ <color name="i_am_color_16ad">#000016ad</color>
+ <color name="i_am_color_16ae">#000016ae</color>
+ <color name="i_am_color_16af">#000016af</color>
+ <color name="i_am_color_16b0">#000016b0</color>
+ <color name="i_am_color_16b1">#000016b1</color>
+ <color name="i_am_color_16b2">#000016b2</color>
+ <color name="i_am_color_16b3">#000016b3</color>
+ <color name="i_am_color_16b4">#000016b4</color>
+ <color name="i_am_color_16b5">#000016b5</color>
+ <color name="i_am_color_16b6">#000016b6</color>
+ <color name="i_am_color_16b7">#000016b7</color>
+ <color name="i_am_color_16b8">#000016b8</color>
+ <color name="i_am_color_16b9">#000016b9</color>
+ <color name="i_am_color_16ba">#000016ba</color>
+ <color name="i_am_color_16bb">#000016bb</color>
+ <color name="i_am_color_16bc">#000016bc</color>
+ <color name="i_am_color_16bd">#000016bd</color>
+ <color name="i_am_color_16be">#000016be</color>
+ <color name="i_am_color_16bf">#000016bf</color>
+ <color name="i_am_color_16c0">#000016c0</color>
+ <color name="i_am_color_16c1">#000016c1</color>
+ <color name="i_am_color_16c2">#000016c2</color>
+ <color name="i_am_color_16c3">#000016c3</color>
+ <color name="i_am_color_16c4">#000016c4</color>
+ <color name="i_am_color_16c5">#000016c5</color>
+ <color name="i_am_color_16c6">#000016c6</color>
+ <color name="i_am_color_16c7">#000016c7</color>
+ <color name="i_am_color_16c8">#000016c8</color>
+ <color name="i_am_color_16c9">#000016c9</color>
+ <color name="i_am_color_16ca">#000016ca</color>
+ <color name="i_am_color_16cb">#000016cb</color>
+ <color name="i_am_color_16cc">#000016cc</color>
+ <color name="i_am_color_16cd">#000016cd</color>
+ <color name="i_am_color_16ce">#000016ce</color>
+ <color name="i_am_color_16cf">#000016cf</color>
+ <color name="i_am_color_16d0">#000016d0</color>
+ <color name="i_am_color_16d1">#000016d1</color>
+ <color name="i_am_color_16d2">#000016d2</color>
+ <color name="i_am_color_16d3">#000016d3</color>
+ <color name="i_am_color_16d4">#000016d4</color>
+ <color name="i_am_color_16d5">#000016d5</color>
+ <color name="i_am_color_16d6">#000016d6</color>
+ <color name="i_am_color_16d7">#000016d7</color>
+ <color name="i_am_color_16d8">#000016d8</color>
+ <color name="i_am_color_16d9">#000016d9</color>
+ <color name="i_am_color_16da">#000016da</color>
+ <color name="i_am_color_16db">#000016db</color>
+ <color name="i_am_color_16dc">#000016dc</color>
+ <color name="i_am_color_16dd">#000016dd</color>
+ <color name="i_am_color_16de">#000016de</color>
+ <color name="i_am_color_16df">#000016df</color>
+ <color name="i_am_color_16e0">#000016e0</color>
+ <color name="i_am_color_16e1">#000016e1</color>
+ <color name="i_am_color_16e2">#000016e2</color>
+ <color name="i_am_color_16e3">#000016e3</color>
+ <color name="i_am_color_16e4">#000016e4</color>
+ <color name="i_am_color_16e5">#000016e5</color>
+ <color name="i_am_color_16e6">#000016e6</color>
+ <color name="i_am_color_16e7">#000016e7</color>
+ <color name="i_am_color_16e8">#000016e8</color>
+ <color name="i_am_color_16e9">#000016e9</color>
+ <color name="i_am_color_16ea">#000016ea</color>
+ <color name="i_am_color_16eb">#000016eb</color>
+ <color name="i_am_color_16ec">#000016ec</color>
+ <color name="i_am_color_16ed">#000016ed</color>
+ <color name="i_am_color_16ee">#000016ee</color>
+ <color name="i_am_color_16ef">#000016ef</color>
+ <color name="i_am_color_16f0">#000016f0</color>
+ <color name="i_am_color_16f1">#000016f1</color>
+ <color name="i_am_color_16f2">#000016f2</color>
+ <color name="i_am_color_16f3">#000016f3</color>
+ <color name="i_am_color_16f4">#000016f4</color>
+ <color name="i_am_color_16f5">#000016f5</color>
+ <color name="i_am_color_16f6">#000016f6</color>
+ <color name="i_am_color_16f7">#000016f7</color>
+ <color name="i_am_color_16f8">#000016f8</color>
+ <color name="i_am_color_16f9">#000016f9</color>
+ <color name="i_am_color_16fa">#000016fa</color>
+ <color name="i_am_color_16fb">#000016fb</color>
+ <color name="i_am_color_16fc">#000016fc</color>
+ <color name="i_am_color_16fd">#000016fd</color>
+ <color name="i_am_color_16fe">#000016fe</color>
+ <color name="i_am_color_16ff">#000016ff</color>
+ <color name="i_am_color_1700">#00001700</color>
+ <color name="i_am_color_1701">#00001701</color>
+ <color name="i_am_color_1702">#00001702</color>
+ <color name="i_am_color_1703">#00001703</color>
+ <color name="i_am_color_1704">#00001704</color>
+ <color name="i_am_color_1705">#00001705</color>
+ <color name="i_am_color_1706">#00001706</color>
+ <color name="i_am_color_1707">#00001707</color>
+ <color name="i_am_color_1708">#00001708</color>
+ <color name="i_am_color_1709">#00001709</color>
+ <color name="i_am_color_170a">#0000170a</color>
+ <color name="i_am_color_170b">#0000170b</color>
+ <color name="i_am_color_170c">#0000170c</color>
+ <color name="i_am_color_170d">#0000170d</color>
+ <color name="i_am_color_170e">#0000170e</color>
+ <color name="i_am_color_170f">#0000170f</color>
+ <color name="i_am_color_1710">#00001710</color>
+ <color name="i_am_color_1711">#00001711</color>
+ <color name="i_am_color_1712">#00001712</color>
+ <color name="i_am_color_1713">#00001713</color>
+ <color name="i_am_color_1714">#00001714</color>
+ <color name="i_am_color_1715">#00001715</color>
+ <color name="i_am_color_1716">#00001716</color>
+ <color name="i_am_color_1717">#00001717</color>
+ <color name="i_am_color_1718">#00001718</color>
+ <color name="i_am_color_1719">#00001719</color>
+ <color name="i_am_color_171a">#0000171a</color>
+ <color name="i_am_color_171b">#0000171b</color>
+ <color name="i_am_color_171c">#0000171c</color>
+ <color name="i_am_color_171d">#0000171d</color>
+ <color name="i_am_color_171e">#0000171e</color>
+ <color name="i_am_color_171f">#0000171f</color>
+ <color name="i_am_color_1720">#00001720</color>
+ <color name="i_am_color_1721">#00001721</color>
+ <color name="i_am_color_1722">#00001722</color>
+ <color name="i_am_color_1723">#00001723</color>
+ <color name="i_am_color_1724">#00001724</color>
+ <color name="i_am_color_1725">#00001725</color>
+ <color name="i_am_color_1726">#00001726</color>
+ <color name="i_am_color_1727">#00001727</color>
+ <color name="i_am_color_1728">#00001728</color>
+ <color name="i_am_color_1729">#00001729</color>
+ <color name="i_am_color_172a">#0000172a</color>
+ <color name="i_am_color_172b">#0000172b</color>
+ <color name="i_am_color_172c">#0000172c</color>
+ <color name="i_am_color_172d">#0000172d</color>
+ <color name="i_am_color_172e">#0000172e</color>
+ <color name="i_am_color_172f">#0000172f</color>
+ <color name="i_am_color_1730">#00001730</color>
+ <color name="i_am_color_1731">#00001731</color>
+ <color name="i_am_color_1732">#00001732</color>
+ <color name="i_am_color_1733">#00001733</color>
+ <color name="i_am_color_1734">#00001734</color>
+ <color name="i_am_color_1735">#00001735</color>
+ <color name="i_am_color_1736">#00001736</color>
+ <color name="i_am_color_1737">#00001737</color>
+ <color name="i_am_color_1738">#00001738</color>
+ <color name="i_am_color_1739">#00001739</color>
+ <color name="i_am_color_173a">#0000173a</color>
+ <color name="i_am_color_173b">#0000173b</color>
+ <color name="i_am_color_173c">#0000173c</color>
+ <color name="i_am_color_173d">#0000173d</color>
+ <color name="i_am_color_173e">#0000173e</color>
+ <color name="i_am_color_173f">#0000173f</color>
+ <color name="i_am_color_1740">#00001740</color>
+ <color name="i_am_color_1741">#00001741</color>
+ <color name="i_am_color_1742">#00001742</color>
+ <color name="i_am_color_1743">#00001743</color>
+ <color name="i_am_color_1744">#00001744</color>
+ <color name="i_am_color_1745">#00001745</color>
+ <color name="i_am_color_1746">#00001746</color>
+ <color name="i_am_color_1747">#00001747</color>
+ <color name="i_am_color_1748">#00001748</color>
+ <color name="i_am_color_1749">#00001749</color>
+ <color name="i_am_color_174a">#0000174a</color>
+ <color name="i_am_color_174b">#0000174b</color>
+ <color name="i_am_color_174c">#0000174c</color>
+ <color name="i_am_color_174d">#0000174d</color>
+ <color name="i_am_color_174e">#0000174e</color>
+ <color name="i_am_color_174f">#0000174f</color>
+ <color name="i_am_color_1750">#00001750</color>
+ <color name="i_am_color_1751">#00001751</color>
+ <color name="i_am_color_1752">#00001752</color>
+ <color name="i_am_color_1753">#00001753</color>
+ <color name="i_am_color_1754">#00001754</color>
+ <color name="i_am_color_1755">#00001755</color>
+ <color name="i_am_color_1756">#00001756</color>
+ <color name="i_am_color_1757">#00001757</color>
+ <color name="i_am_color_1758">#00001758</color>
+ <color name="i_am_color_1759">#00001759</color>
+ <color name="i_am_color_175a">#0000175a</color>
+ <color name="i_am_color_175b">#0000175b</color>
+ <color name="i_am_color_175c">#0000175c</color>
+ <color name="i_am_color_175d">#0000175d</color>
+ <color name="i_am_color_175e">#0000175e</color>
+ <color name="i_am_color_175f">#0000175f</color>
+ <color name="i_am_color_1760">#00001760</color>
+ <color name="i_am_color_1761">#00001761</color>
+ <color name="i_am_color_1762">#00001762</color>
+ <color name="i_am_color_1763">#00001763</color>
+ <color name="i_am_color_1764">#00001764</color>
+ <color name="i_am_color_1765">#00001765</color>
+ <color name="i_am_color_1766">#00001766</color>
+ <color name="i_am_color_1767">#00001767</color>
+ <color name="i_am_color_1768">#00001768</color>
+ <color name="i_am_color_1769">#00001769</color>
+ <color name="i_am_color_176a">#0000176a</color>
+ <color name="i_am_color_176b">#0000176b</color>
+ <color name="i_am_color_176c">#0000176c</color>
+ <color name="i_am_color_176d">#0000176d</color>
+ <color name="i_am_color_176e">#0000176e</color>
+ <color name="i_am_color_176f">#0000176f</color>
+ <color name="i_am_color_1770">#00001770</color>
+ <color name="i_am_color_1771">#00001771</color>
+ <color name="i_am_color_1772">#00001772</color>
+ <color name="i_am_color_1773">#00001773</color>
+ <color name="i_am_color_1774">#00001774</color>
+ <color name="i_am_color_1775">#00001775</color>
+ <color name="i_am_color_1776">#00001776</color>
+ <color name="i_am_color_1777">#00001777</color>
+ <color name="i_am_color_1778">#00001778</color>
+ <color name="i_am_color_1779">#00001779</color>
+ <color name="i_am_color_177a">#0000177a</color>
+ <color name="i_am_color_177b">#0000177b</color>
+ <color name="i_am_color_177c">#0000177c</color>
+ <color name="i_am_color_177d">#0000177d</color>
+ <color name="i_am_color_177e">#0000177e</color>
+ <color name="i_am_color_177f">#0000177f</color>
+ <color name="i_am_color_1780">#00001780</color>
+ <color name="i_am_color_1781">#00001781</color>
+ <color name="i_am_color_1782">#00001782</color>
+ <color name="i_am_color_1783">#00001783</color>
+ <color name="i_am_color_1784">#00001784</color>
+ <color name="i_am_color_1785">#00001785</color>
+ <color name="i_am_color_1786">#00001786</color>
+ <color name="i_am_color_1787">#00001787</color>
+ <color name="i_am_color_1788">#00001788</color>
+ <color name="i_am_color_1789">#00001789</color>
+ <color name="i_am_color_178a">#0000178a</color>
+ <color name="i_am_color_178b">#0000178b</color>
+ <color name="i_am_color_178c">#0000178c</color>
+ <color name="i_am_color_178d">#0000178d</color>
+ <color name="i_am_color_178e">#0000178e</color>
+ <color name="i_am_color_178f">#0000178f</color>
+ <color name="i_am_color_1790">#00001790</color>
+ <color name="i_am_color_1791">#00001791</color>
+ <color name="i_am_color_1792">#00001792</color>
+ <color name="i_am_color_1793">#00001793</color>
+ <color name="i_am_color_1794">#00001794</color>
+ <color name="i_am_color_1795">#00001795</color>
+ <color name="i_am_color_1796">#00001796</color>
+ <color name="i_am_color_1797">#00001797</color>
+ <color name="i_am_color_1798">#00001798</color>
+ <color name="i_am_color_1799">#00001799</color>
+ <color name="i_am_color_179a">#0000179a</color>
+ <color name="i_am_color_179b">#0000179b</color>
+ <color name="i_am_color_179c">#0000179c</color>
+ <color name="i_am_color_179d">#0000179d</color>
+ <color name="i_am_color_179e">#0000179e</color>
+ <color name="i_am_color_179f">#0000179f</color>
+ <color name="i_am_color_17a0">#000017a0</color>
+ <color name="i_am_color_17a1">#000017a1</color>
+ <color name="i_am_color_17a2">#000017a2</color>
+ <color name="i_am_color_17a3">#000017a3</color>
+ <color name="i_am_color_17a4">#000017a4</color>
+ <color name="i_am_color_17a5">#000017a5</color>
+ <color name="i_am_color_17a6">#000017a6</color>
+ <color name="i_am_color_17a7">#000017a7</color>
+ <color name="i_am_color_17a8">#000017a8</color>
+ <color name="i_am_color_17a9">#000017a9</color>
+ <color name="i_am_color_17aa">#000017aa</color>
+ <color name="i_am_color_17ab">#000017ab</color>
+ <color name="i_am_color_17ac">#000017ac</color>
+ <color name="i_am_color_17ad">#000017ad</color>
+ <color name="i_am_color_17ae">#000017ae</color>
+ <color name="i_am_color_17af">#000017af</color>
+ <color name="i_am_color_17b0">#000017b0</color>
+ <color name="i_am_color_17b1">#000017b1</color>
+ <color name="i_am_color_17b2">#000017b2</color>
+ <color name="i_am_color_17b3">#000017b3</color>
+ <color name="i_am_color_17b4">#000017b4</color>
+ <color name="i_am_color_17b5">#000017b5</color>
+ <color name="i_am_color_17b6">#000017b6</color>
+ <color name="i_am_color_17b7">#000017b7</color>
+ <color name="i_am_color_17b8">#000017b8</color>
+ <color name="i_am_color_17b9">#000017b9</color>
+ <color name="i_am_color_17ba">#000017ba</color>
+ <color name="i_am_color_17bb">#000017bb</color>
+ <color name="i_am_color_17bc">#000017bc</color>
+ <color name="i_am_color_17bd">#000017bd</color>
+ <color name="i_am_color_17be">#000017be</color>
+ <color name="i_am_color_17bf">#000017bf</color>
+ <color name="i_am_color_17c0">#000017c0</color>
+ <color name="i_am_color_17c1">#000017c1</color>
+ <color name="i_am_color_17c2">#000017c2</color>
+ <color name="i_am_color_17c3">#000017c3</color>
+ <color name="i_am_color_17c4">#000017c4</color>
+ <color name="i_am_color_17c5">#000017c5</color>
+ <color name="i_am_color_17c6">#000017c6</color>
+ <color name="i_am_color_17c7">#000017c7</color>
+ <color name="i_am_color_17c8">#000017c8</color>
+ <color name="i_am_color_17c9">#000017c9</color>
+ <color name="i_am_color_17ca">#000017ca</color>
+ <color name="i_am_color_17cb">#000017cb</color>
+ <color name="i_am_color_17cc">#000017cc</color>
+ <color name="i_am_color_17cd">#000017cd</color>
+ <color name="i_am_color_17ce">#000017ce</color>
+ <color name="i_am_color_17cf">#000017cf</color>
+ <color name="i_am_color_17d0">#000017d0</color>
+ <color name="i_am_color_17d1">#000017d1</color>
+ <color name="i_am_color_17d2">#000017d2</color>
+ <color name="i_am_color_17d3">#000017d3</color>
+ <color name="i_am_color_17d4">#000017d4</color>
+ <color name="i_am_color_17d5">#000017d5</color>
+ <color name="i_am_color_17d6">#000017d6</color>
+ <color name="i_am_color_17d7">#000017d7</color>
+ <color name="i_am_color_17d8">#000017d8</color>
+ <color name="i_am_color_17d9">#000017d9</color>
+ <color name="i_am_color_17da">#000017da</color>
+ <color name="i_am_color_17db">#000017db</color>
+ <color name="i_am_color_17dc">#000017dc</color>
+ <color name="i_am_color_17dd">#000017dd</color>
+ <color name="i_am_color_17de">#000017de</color>
+ <color name="i_am_color_17df">#000017df</color>
+ <color name="i_am_color_17e0">#000017e0</color>
+ <color name="i_am_color_17e1">#000017e1</color>
+ <color name="i_am_color_17e2">#000017e2</color>
+ <color name="i_am_color_17e3">#000017e3</color>
+ <color name="i_am_color_17e4">#000017e4</color>
+ <color name="i_am_color_17e5">#000017e5</color>
+ <color name="i_am_color_17e6">#000017e6</color>
+ <color name="i_am_color_17e7">#000017e7</color>
+ <color name="i_am_color_17e8">#000017e8</color>
+ <color name="i_am_color_17e9">#000017e9</color>
+ <color name="i_am_color_17ea">#000017ea</color>
+ <color name="i_am_color_17eb">#000017eb</color>
+ <color name="i_am_color_17ec">#000017ec</color>
+ <color name="i_am_color_17ed">#000017ed</color>
+ <color name="i_am_color_17ee">#000017ee</color>
+ <color name="i_am_color_17ef">#000017ef</color>
+ <color name="i_am_color_17f0">#000017f0</color>
+ <color name="i_am_color_17f1">#000017f1</color>
+ <color name="i_am_color_17f2">#000017f2</color>
+ <color name="i_am_color_17f3">#000017f3</color>
+ <color name="i_am_color_17f4">#000017f4</color>
+ <color name="i_am_color_17f5">#000017f5</color>
+ <color name="i_am_color_17f6">#000017f6</color>
+ <color name="i_am_color_17f7">#000017f7</color>
+ <color name="i_am_color_17f8">#000017f8</color>
+ <color name="i_am_color_17f9">#000017f9</color>
+ <color name="i_am_color_17fa">#000017fa</color>
+ <color name="i_am_color_17fb">#000017fb</color>
+ <color name="i_am_color_17fc">#000017fc</color>
+ <color name="i_am_color_17fd">#000017fd</color>
+ <color name="i_am_color_17fe">#000017fe</color>
+ <color name="i_am_color_17ff">#000017ff</color>
+ <color name="i_am_color_1800">#00001800</color>
+ <color name="i_am_color_1801">#00001801</color>
+ <color name="i_am_color_1802">#00001802</color>
+ <color name="i_am_color_1803">#00001803</color>
+ <color name="i_am_color_1804">#00001804</color>
+ <color name="i_am_color_1805">#00001805</color>
+ <color name="i_am_color_1806">#00001806</color>
+ <color name="i_am_color_1807">#00001807</color>
+ <color name="i_am_color_1808">#00001808</color>
+ <color name="i_am_color_1809">#00001809</color>
+ <color name="i_am_color_180a">#0000180a</color>
+ <color name="i_am_color_180b">#0000180b</color>
+ <color name="i_am_color_180c">#0000180c</color>
+ <color name="i_am_color_180d">#0000180d</color>
+ <color name="i_am_color_180e">#0000180e</color>
+ <color name="i_am_color_180f">#0000180f</color>
+ <color name="i_am_color_1810">#00001810</color>
+ <color name="i_am_color_1811">#00001811</color>
+ <color name="i_am_color_1812">#00001812</color>
+ <color name="i_am_color_1813">#00001813</color>
+ <color name="i_am_color_1814">#00001814</color>
+ <color name="i_am_color_1815">#00001815</color>
+ <color name="i_am_color_1816">#00001816</color>
+ <color name="i_am_color_1817">#00001817</color>
+ <color name="i_am_color_1818">#00001818</color>
+ <color name="i_am_color_1819">#00001819</color>
+ <color name="i_am_color_181a">#0000181a</color>
+ <color name="i_am_color_181b">#0000181b</color>
+ <color name="i_am_color_181c">#0000181c</color>
+ <color name="i_am_color_181d">#0000181d</color>
+ <color name="i_am_color_181e">#0000181e</color>
+ <color name="i_am_color_181f">#0000181f</color>
+ <color name="i_am_color_1820">#00001820</color>
+ <color name="i_am_color_1821">#00001821</color>
+ <color name="i_am_color_1822">#00001822</color>
+ <color name="i_am_color_1823">#00001823</color>
+ <color name="i_am_color_1824">#00001824</color>
+ <color name="i_am_color_1825">#00001825</color>
+ <color name="i_am_color_1826">#00001826</color>
+ <color name="i_am_color_1827">#00001827</color>
+ <color name="i_am_color_1828">#00001828</color>
+ <color name="i_am_color_1829">#00001829</color>
+ <color name="i_am_color_182a">#0000182a</color>
+ <color name="i_am_color_182b">#0000182b</color>
+ <color name="i_am_color_182c">#0000182c</color>
+ <color name="i_am_color_182d">#0000182d</color>
+ <color name="i_am_color_182e">#0000182e</color>
+ <color name="i_am_color_182f">#0000182f</color>
+ <color name="i_am_color_1830">#00001830</color>
+ <color name="i_am_color_1831">#00001831</color>
+ <color name="i_am_color_1832">#00001832</color>
+ <color name="i_am_color_1833">#00001833</color>
+ <color name="i_am_color_1834">#00001834</color>
+ <color name="i_am_color_1835">#00001835</color>
+ <color name="i_am_color_1836">#00001836</color>
+ <color name="i_am_color_1837">#00001837</color>
+ <color name="i_am_color_1838">#00001838</color>
+ <color name="i_am_color_1839">#00001839</color>
+ <color name="i_am_color_183a">#0000183a</color>
+ <color name="i_am_color_183b">#0000183b</color>
+ <color name="i_am_color_183c">#0000183c</color>
+ <color name="i_am_color_183d">#0000183d</color>
+ <color name="i_am_color_183e">#0000183e</color>
+ <color name="i_am_color_183f">#0000183f</color>
+ <color name="i_am_color_1840">#00001840</color>
+ <color name="i_am_color_1841">#00001841</color>
+ <color name="i_am_color_1842">#00001842</color>
+ <color name="i_am_color_1843">#00001843</color>
+ <color name="i_am_color_1844">#00001844</color>
+ <color name="i_am_color_1845">#00001845</color>
+ <color name="i_am_color_1846">#00001846</color>
+ <color name="i_am_color_1847">#00001847</color>
+ <color name="i_am_color_1848">#00001848</color>
+ <color name="i_am_color_1849">#00001849</color>
+ <color name="i_am_color_184a">#0000184a</color>
+ <color name="i_am_color_184b">#0000184b</color>
+ <color name="i_am_color_184c">#0000184c</color>
+ <color name="i_am_color_184d">#0000184d</color>
+ <color name="i_am_color_184e">#0000184e</color>
+ <color name="i_am_color_184f">#0000184f</color>
+ <color name="i_am_color_1850">#00001850</color>
+ <color name="i_am_color_1851">#00001851</color>
+ <color name="i_am_color_1852">#00001852</color>
+ <color name="i_am_color_1853">#00001853</color>
+ <color name="i_am_color_1854">#00001854</color>
+ <color name="i_am_color_1855">#00001855</color>
+ <color name="i_am_color_1856">#00001856</color>
+ <color name="i_am_color_1857">#00001857</color>
+ <color name="i_am_color_1858">#00001858</color>
+ <color name="i_am_color_1859">#00001859</color>
+ <color name="i_am_color_185a">#0000185a</color>
+ <color name="i_am_color_185b">#0000185b</color>
+ <color name="i_am_color_185c">#0000185c</color>
+ <color name="i_am_color_185d">#0000185d</color>
+ <color name="i_am_color_185e">#0000185e</color>
+ <color name="i_am_color_185f">#0000185f</color>
+ <color name="i_am_color_1860">#00001860</color>
+ <color name="i_am_color_1861">#00001861</color>
+ <color name="i_am_color_1862">#00001862</color>
+ <color name="i_am_color_1863">#00001863</color>
+ <color name="i_am_color_1864">#00001864</color>
+ <color name="i_am_color_1865">#00001865</color>
+ <color name="i_am_color_1866">#00001866</color>
+ <color name="i_am_color_1867">#00001867</color>
+ <color name="i_am_color_1868">#00001868</color>
+ <color name="i_am_color_1869">#00001869</color>
+ <color name="i_am_color_186a">#0000186a</color>
+ <color name="i_am_color_186b">#0000186b</color>
+ <color name="i_am_color_186c">#0000186c</color>
+ <color name="i_am_color_186d">#0000186d</color>
+ <color name="i_am_color_186e">#0000186e</color>
+ <color name="i_am_color_186f">#0000186f</color>
+ <color name="i_am_color_1870">#00001870</color>
+ <color name="i_am_color_1871">#00001871</color>
+ <color name="i_am_color_1872">#00001872</color>
+ <color name="i_am_color_1873">#00001873</color>
+ <color name="i_am_color_1874">#00001874</color>
+ <color name="i_am_color_1875">#00001875</color>
+ <color name="i_am_color_1876">#00001876</color>
+ <color name="i_am_color_1877">#00001877</color>
+ <color name="i_am_color_1878">#00001878</color>
+ <color name="i_am_color_1879">#00001879</color>
+ <color name="i_am_color_187a">#0000187a</color>
+ <color name="i_am_color_187b">#0000187b</color>
+ <color name="i_am_color_187c">#0000187c</color>
+ <color name="i_am_color_187d">#0000187d</color>
+ <color name="i_am_color_187e">#0000187e</color>
+ <color name="i_am_color_187f">#0000187f</color>
+ <color name="i_am_color_1880">#00001880</color>
+ <color name="i_am_color_1881">#00001881</color>
+ <color name="i_am_color_1882">#00001882</color>
+ <color name="i_am_color_1883">#00001883</color>
+ <color name="i_am_color_1884">#00001884</color>
+ <color name="i_am_color_1885">#00001885</color>
+ <color name="i_am_color_1886">#00001886</color>
+ <color name="i_am_color_1887">#00001887</color>
+ <color name="i_am_color_1888">#00001888</color>
+ <color name="i_am_color_1889">#00001889</color>
+ <color name="i_am_color_188a">#0000188a</color>
+ <color name="i_am_color_188b">#0000188b</color>
+ <color name="i_am_color_188c">#0000188c</color>
+ <color name="i_am_color_188d">#0000188d</color>
+ <color name="i_am_color_188e">#0000188e</color>
+ <color name="i_am_color_188f">#0000188f</color>
+ <color name="i_am_color_1890">#00001890</color>
+ <color name="i_am_color_1891">#00001891</color>
+ <color name="i_am_color_1892">#00001892</color>
+ <color name="i_am_color_1893">#00001893</color>
+ <color name="i_am_color_1894">#00001894</color>
+ <color name="i_am_color_1895">#00001895</color>
+ <color name="i_am_color_1896">#00001896</color>
+ <color name="i_am_color_1897">#00001897</color>
+ <color name="i_am_color_1898">#00001898</color>
+ <color name="i_am_color_1899">#00001899</color>
+ <color name="i_am_color_189a">#0000189a</color>
+ <color name="i_am_color_189b">#0000189b</color>
+ <color name="i_am_color_189c">#0000189c</color>
+ <color name="i_am_color_189d">#0000189d</color>
+ <color name="i_am_color_189e">#0000189e</color>
+ <color name="i_am_color_189f">#0000189f</color>
+ <color name="i_am_color_18a0">#000018a0</color>
+ <color name="i_am_color_18a1">#000018a1</color>
+ <color name="i_am_color_18a2">#000018a2</color>
+ <color name="i_am_color_18a3">#000018a3</color>
+ <color name="i_am_color_18a4">#000018a4</color>
+ <color name="i_am_color_18a5">#000018a5</color>
+ <color name="i_am_color_18a6">#000018a6</color>
+ <color name="i_am_color_18a7">#000018a7</color>
+ <color name="i_am_color_18a8">#000018a8</color>
+ <color name="i_am_color_18a9">#000018a9</color>
+ <color name="i_am_color_18aa">#000018aa</color>
+ <color name="i_am_color_18ab">#000018ab</color>
+ <color name="i_am_color_18ac">#000018ac</color>
+ <color name="i_am_color_18ad">#000018ad</color>
+ <color name="i_am_color_18ae">#000018ae</color>
+ <color name="i_am_color_18af">#000018af</color>
+ <color name="i_am_color_18b0">#000018b0</color>
+ <color name="i_am_color_18b1">#000018b1</color>
+ <color name="i_am_color_18b2">#000018b2</color>
+ <color name="i_am_color_18b3">#000018b3</color>
+ <color name="i_am_color_18b4">#000018b4</color>
+ <color name="i_am_color_18b5">#000018b5</color>
+ <color name="i_am_color_18b6">#000018b6</color>
+ <color name="i_am_color_18b7">#000018b7</color>
+ <color name="i_am_color_18b8">#000018b8</color>
+ <color name="i_am_color_18b9">#000018b9</color>
+ <color name="i_am_color_18ba">#000018ba</color>
+ <color name="i_am_color_18bb">#000018bb</color>
+ <color name="i_am_color_18bc">#000018bc</color>
+ <color name="i_am_color_18bd">#000018bd</color>
+ <color name="i_am_color_18be">#000018be</color>
+ <color name="i_am_color_18bf">#000018bf</color>
+ <color name="i_am_color_18c0">#000018c0</color>
+ <color name="i_am_color_18c1">#000018c1</color>
+ <color name="i_am_color_18c2">#000018c2</color>
+ <color name="i_am_color_18c3">#000018c3</color>
+ <color name="i_am_color_18c4">#000018c4</color>
+ <color name="i_am_color_18c5">#000018c5</color>
+ <color name="i_am_color_18c6">#000018c6</color>
+ <color name="i_am_color_18c7">#000018c7</color>
+ <color name="i_am_color_18c8">#000018c8</color>
+ <color name="i_am_color_18c9">#000018c9</color>
+ <color name="i_am_color_18ca">#000018ca</color>
+ <color name="i_am_color_18cb">#000018cb</color>
+ <color name="i_am_color_18cc">#000018cc</color>
+ <color name="i_am_color_18cd">#000018cd</color>
+ <color name="i_am_color_18ce">#000018ce</color>
+ <color name="i_am_color_18cf">#000018cf</color>
+ <color name="i_am_color_18d0">#000018d0</color>
+ <color name="i_am_color_18d1">#000018d1</color>
+ <color name="i_am_color_18d2">#000018d2</color>
+ <color name="i_am_color_18d3">#000018d3</color>
+ <color name="i_am_color_18d4">#000018d4</color>
+ <color name="i_am_color_18d5">#000018d5</color>
+ <color name="i_am_color_18d6">#000018d6</color>
+ <color name="i_am_color_18d7">#000018d7</color>
+ <color name="i_am_color_18d8">#000018d8</color>
+ <color name="i_am_color_18d9">#000018d9</color>
+ <color name="i_am_color_18da">#000018da</color>
+ <color name="i_am_color_18db">#000018db</color>
+ <color name="i_am_color_18dc">#000018dc</color>
+ <color name="i_am_color_18dd">#000018dd</color>
+ <color name="i_am_color_18de">#000018de</color>
+ <color name="i_am_color_18df">#000018df</color>
+ <color name="i_am_color_18e0">#000018e0</color>
+ <color name="i_am_color_18e1">#000018e1</color>
+ <color name="i_am_color_18e2">#000018e2</color>
+ <color name="i_am_color_18e3">#000018e3</color>
+ <color name="i_am_color_18e4">#000018e4</color>
+ <color name="i_am_color_18e5">#000018e5</color>
+ <color name="i_am_color_18e6">#000018e6</color>
+ <color name="i_am_color_18e7">#000018e7</color>
+ <color name="i_am_color_18e8">#000018e8</color>
+ <color name="i_am_color_18e9">#000018e9</color>
+ <color name="i_am_color_18ea">#000018ea</color>
+ <color name="i_am_color_18eb">#000018eb</color>
+ <color name="i_am_color_18ec">#000018ec</color>
+ <color name="i_am_color_18ed">#000018ed</color>
+ <color name="i_am_color_18ee">#000018ee</color>
+ <color name="i_am_color_18ef">#000018ef</color>
+ <color name="i_am_color_18f0">#000018f0</color>
+ <color name="i_am_color_18f1">#000018f1</color>
+ <color name="i_am_color_18f2">#000018f2</color>
+ <color name="i_am_color_18f3">#000018f3</color>
+ <color name="i_am_color_18f4">#000018f4</color>
+ <color name="i_am_color_18f5">#000018f5</color>
+ <color name="i_am_color_18f6">#000018f6</color>
+ <color name="i_am_color_18f7">#000018f7</color>
+ <color name="i_am_color_18f8">#000018f8</color>
+ <color name="i_am_color_18f9">#000018f9</color>
+ <color name="i_am_color_18fa">#000018fa</color>
+ <color name="i_am_color_18fb">#000018fb</color>
+ <color name="i_am_color_18fc">#000018fc</color>
+ <color name="i_am_color_18fd">#000018fd</color>
+ <color name="i_am_color_18fe">#000018fe</color>
+ <color name="i_am_color_18ff">#000018ff</color>
+ <color name="i_am_color_1900">#00001900</color>
+ <color name="i_am_color_1901">#00001901</color>
+ <color name="i_am_color_1902">#00001902</color>
+ <color name="i_am_color_1903">#00001903</color>
+ <color name="i_am_color_1904">#00001904</color>
+ <color name="i_am_color_1905">#00001905</color>
+ <color name="i_am_color_1906">#00001906</color>
+ <color name="i_am_color_1907">#00001907</color>
+ <color name="i_am_color_1908">#00001908</color>
+ <color name="i_am_color_1909">#00001909</color>
+ <color name="i_am_color_190a">#0000190a</color>
+ <color name="i_am_color_190b">#0000190b</color>
+ <color name="i_am_color_190c">#0000190c</color>
+ <color name="i_am_color_190d">#0000190d</color>
+ <color name="i_am_color_190e">#0000190e</color>
+ <color name="i_am_color_190f">#0000190f</color>
+ <color name="i_am_color_1910">#00001910</color>
+ <color name="i_am_color_1911">#00001911</color>
+ <color name="i_am_color_1912">#00001912</color>
+ <color name="i_am_color_1913">#00001913</color>
+ <color name="i_am_color_1914">#00001914</color>
+ <color name="i_am_color_1915">#00001915</color>
+ <color name="i_am_color_1916">#00001916</color>
+ <color name="i_am_color_1917">#00001917</color>
+ <color name="i_am_color_1918">#00001918</color>
+ <color name="i_am_color_1919">#00001919</color>
+ <color name="i_am_color_191a">#0000191a</color>
+ <color name="i_am_color_191b">#0000191b</color>
+ <color name="i_am_color_191c">#0000191c</color>
+ <color name="i_am_color_191d">#0000191d</color>
+ <color name="i_am_color_191e">#0000191e</color>
+ <color name="i_am_color_191f">#0000191f</color>
+ <color name="i_am_color_1920">#00001920</color>
+ <color name="i_am_color_1921">#00001921</color>
+ <color name="i_am_color_1922">#00001922</color>
+ <color name="i_am_color_1923">#00001923</color>
+ <color name="i_am_color_1924">#00001924</color>
+ <color name="i_am_color_1925">#00001925</color>
+ <color name="i_am_color_1926">#00001926</color>
+ <color name="i_am_color_1927">#00001927</color>
+ <color name="i_am_color_1928">#00001928</color>
+ <color name="i_am_color_1929">#00001929</color>
+ <color name="i_am_color_192a">#0000192a</color>
+ <color name="i_am_color_192b">#0000192b</color>
+ <color name="i_am_color_192c">#0000192c</color>
+ <color name="i_am_color_192d">#0000192d</color>
+ <color name="i_am_color_192e">#0000192e</color>
+ <color name="i_am_color_192f">#0000192f</color>
+ <color name="i_am_color_1930">#00001930</color>
+ <color name="i_am_color_1931">#00001931</color>
+ <color name="i_am_color_1932">#00001932</color>
+ <color name="i_am_color_1933">#00001933</color>
+ <color name="i_am_color_1934">#00001934</color>
+ <color name="i_am_color_1935">#00001935</color>
+ <color name="i_am_color_1936">#00001936</color>
+ <color name="i_am_color_1937">#00001937</color>
+ <color name="i_am_color_1938">#00001938</color>
+ <color name="i_am_color_1939">#00001939</color>
+ <color name="i_am_color_193a">#0000193a</color>
+ <color name="i_am_color_193b">#0000193b</color>
+ <color name="i_am_color_193c">#0000193c</color>
+ <color name="i_am_color_193d">#0000193d</color>
+ <color name="i_am_color_193e">#0000193e</color>
+ <color name="i_am_color_193f">#0000193f</color>
+ <color name="i_am_color_1940">#00001940</color>
+ <color name="i_am_color_1941">#00001941</color>
+ <color name="i_am_color_1942">#00001942</color>
+ <color name="i_am_color_1943">#00001943</color>
+ <color name="i_am_color_1944">#00001944</color>
+ <color name="i_am_color_1945">#00001945</color>
+ <color name="i_am_color_1946">#00001946</color>
+ <color name="i_am_color_1947">#00001947</color>
+ <color name="i_am_color_1948">#00001948</color>
+ <color name="i_am_color_1949">#00001949</color>
+ <color name="i_am_color_194a">#0000194a</color>
+ <color name="i_am_color_194b">#0000194b</color>
+ <color name="i_am_color_194c">#0000194c</color>
+ <color name="i_am_color_194d">#0000194d</color>
+ <color name="i_am_color_194e">#0000194e</color>
+ <color name="i_am_color_194f">#0000194f</color>
+ <color name="i_am_color_1950">#00001950</color>
+ <color name="i_am_color_1951">#00001951</color>
+ <color name="i_am_color_1952">#00001952</color>
+ <color name="i_am_color_1953">#00001953</color>
+ <color name="i_am_color_1954">#00001954</color>
+ <color name="i_am_color_1955">#00001955</color>
+ <color name="i_am_color_1956">#00001956</color>
+ <color name="i_am_color_1957">#00001957</color>
+ <color name="i_am_color_1958">#00001958</color>
+ <color name="i_am_color_1959">#00001959</color>
+ <color name="i_am_color_195a">#0000195a</color>
+ <color name="i_am_color_195b">#0000195b</color>
+ <color name="i_am_color_195c">#0000195c</color>
+ <color name="i_am_color_195d">#0000195d</color>
+ <color name="i_am_color_195e">#0000195e</color>
+ <color name="i_am_color_195f">#0000195f</color>
+ <color name="i_am_color_1960">#00001960</color>
+ <color name="i_am_color_1961">#00001961</color>
+ <color name="i_am_color_1962">#00001962</color>
+ <color name="i_am_color_1963">#00001963</color>
+ <color name="i_am_color_1964">#00001964</color>
+ <color name="i_am_color_1965">#00001965</color>
+ <color name="i_am_color_1966">#00001966</color>
+ <color name="i_am_color_1967">#00001967</color>
+ <color name="i_am_color_1968">#00001968</color>
+ <color name="i_am_color_1969">#00001969</color>
+ <color name="i_am_color_196a">#0000196a</color>
+ <color name="i_am_color_196b">#0000196b</color>
+ <color name="i_am_color_196c">#0000196c</color>
+ <color name="i_am_color_196d">#0000196d</color>
+ <color name="i_am_color_196e">#0000196e</color>
+ <color name="i_am_color_196f">#0000196f</color>
+ <color name="i_am_color_1970">#00001970</color>
+ <color name="i_am_color_1971">#00001971</color>
+ <color name="i_am_color_1972">#00001972</color>
+ <color name="i_am_color_1973">#00001973</color>
+ <color name="i_am_color_1974">#00001974</color>
+ <color name="i_am_color_1975">#00001975</color>
+ <color name="i_am_color_1976">#00001976</color>
+ <color name="i_am_color_1977">#00001977</color>
+ <color name="i_am_color_1978">#00001978</color>
+ <color name="i_am_color_1979">#00001979</color>
+ <color name="i_am_color_197a">#0000197a</color>
+ <color name="i_am_color_197b">#0000197b</color>
+ <color name="i_am_color_197c">#0000197c</color>
+ <color name="i_am_color_197d">#0000197d</color>
+ <color name="i_am_color_197e">#0000197e</color>
+ <color name="i_am_color_197f">#0000197f</color>
+ <color name="i_am_color_1980">#00001980</color>
+ <color name="i_am_color_1981">#00001981</color>
+ <color name="i_am_color_1982">#00001982</color>
+ <color name="i_am_color_1983">#00001983</color>
+ <color name="i_am_color_1984">#00001984</color>
+ <color name="i_am_color_1985">#00001985</color>
+ <color name="i_am_color_1986">#00001986</color>
+ <color name="i_am_color_1987">#00001987</color>
+ <color name="i_am_color_1988">#00001988</color>
+ <color name="i_am_color_1989">#00001989</color>
+ <color name="i_am_color_198a">#0000198a</color>
+ <color name="i_am_color_198b">#0000198b</color>
+ <color name="i_am_color_198c">#0000198c</color>
+ <color name="i_am_color_198d">#0000198d</color>
+ <color name="i_am_color_198e">#0000198e</color>
+ <color name="i_am_color_198f">#0000198f</color>
+ <color name="i_am_color_1990">#00001990</color>
+ <color name="i_am_color_1991">#00001991</color>
+ <color name="i_am_color_1992">#00001992</color>
+ <color name="i_am_color_1993">#00001993</color>
+ <color name="i_am_color_1994">#00001994</color>
+ <color name="i_am_color_1995">#00001995</color>
+ <color name="i_am_color_1996">#00001996</color>
+ <color name="i_am_color_1997">#00001997</color>
+ <color name="i_am_color_1998">#00001998</color>
+ <color name="i_am_color_1999">#00001999</color>
+ <color name="i_am_color_199a">#0000199a</color>
+ <color name="i_am_color_199b">#0000199b</color>
+ <color name="i_am_color_199c">#0000199c</color>
+ <color name="i_am_color_199d">#0000199d</color>
+ <color name="i_am_color_199e">#0000199e</color>
+ <color name="i_am_color_199f">#0000199f</color>
+ <color name="i_am_color_19a0">#000019a0</color>
+ <color name="i_am_color_19a1">#000019a1</color>
+ <color name="i_am_color_19a2">#000019a2</color>
+ <color name="i_am_color_19a3">#000019a3</color>
+ <color name="i_am_color_19a4">#000019a4</color>
+ <color name="i_am_color_19a5">#000019a5</color>
+ <color name="i_am_color_19a6">#000019a6</color>
+ <color name="i_am_color_19a7">#000019a7</color>
+ <color name="i_am_color_19a8">#000019a8</color>
+ <color name="i_am_color_19a9">#000019a9</color>
+ <color name="i_am_color_19aa">#000019aa</color>
+ <color name="i_am_color_19ab">#000019ab</color>
+ <color name="i_am_color_19ac">#000019ac</color>
+ <color name="i_am_color_19ad">#000019ad</color>
+ <color name="i_am_color_19ae">#000019ae</color>
+ <color name="i_am_color_19af">#000019af</color>
+ <color name="i_am_color_19b0">#000019b0</color>
+ <color name="i_am_color_19b1">#000019b1</color>
+ <color name="i_am_color_19b2">#000019b2</color>
+ <color name="i_am_color_19b3">#000019b3</color>
+ <color name="i_am_color_19b4">#000019b4</color>
+ <color name="i_am_color_19b5">#000019b5</color>
+ <color name="i_am_color_19b6">#000019b6</color>
+ <color name="i_am_color_19b7">#000019b7</color>
+ <color name="i_am_color_19b8">#000019b8</color>
+ <color name="i_am_color_19b9">#000019b9</color>
+ <color name="i_am_color_19ba">#000019ba</color>
+ <color name="i_am_color_19bb">#000019bb</color>
+ <color name="i_am_color_19bc">#000019bc</color>
+ <color name="i_am_color_19bd">#000019bd</color>
+ <color name="i_am_color_19be">#000019be</color>
+ <color name="i_am_color_19bf">#000019bf</color>
+ <color name="i_am_color_19c0">#000019c0</color>
+ <color name="i_am_color_19c1">#000019c1</color>
+ <color name="i_am_color_19c2">#000019c2</color>
+ <color name="i_am_color_19c3">#000019c3</color>
+ <color name="i_am_color_19c4">#000019c4</color>
+ <color name="i_am_color_19c5">#000019c5</color>
+ <color name="i_am_color_19c6">#000019c6</color>
+ <color name="i_am_color_19c7">#000019c7</color>
+ <color name="i_am_color_19c8">#000019c8</color>
+ <color name="i_am_color_19c9">#000019c9</color>
+ <color name="i_am_color_19ca">#000019ca</color>
+ <color name="i_am_color_19cb">#000019cb</color>
+ <color name="i_am_color_19cc">#000019cc</color>
+ <color name="i_am_color_19cd">#000019cd</color>
+ <color name="i_am_color_19ce">#000019ce</color>
+ <color name="i_am_color_19cf">#000019cf</color>
+ <color name="i_am_color_19d0">#000019d0</color>
+ <color name="i_am_color_19d1">#000019d1</color>
+ <color name="i_am_color_19d2">#000019d2</color>
+ <color name="i_am_color_19d3">#000019d3</color>
+ <color name="i_am_color_19d4">#000019d4</color>
+ <color name="i_am_color_19d5">#000019d5</color>
+ <color name="i_am_color_19d6">#000019d6</color>
+ <color name="i_am_color_19d7">#000019d7</color>
+ <color name="i_am_color_19d8">#000019d8</color>
+ <color name="i_am_color_19d9">#000019d9</color>
+ <color name="i_am_color_19da">#000019da</color>
+ <color name="i_am_color_19db">#000019db</color>
+ <color name="i_am_color_19dc">#000019dc</color>
+ <color name="i_am_color_19dd">#000019dd</color>
+ <color name="i_am_color_19de">#000019de</color>
+ <color name="i_am_color_19df">#000019df</color>
+ <color name="i_am_color_19e0">#000019e0</color>
+ <color name="i_am_color_19e1">#000019e1</color>
+ <color name="i_am_color_19e2">#000019e2</color>
+ <color name="i_am_color_19e3">#000019e3</color>
+ <color name="i_am_color_19e4">#000019e4</color>
+ <color name="i_am_color_19e5">#000019e5</color>
+ <color name="i_am_color_19e6">#000019e6</color>
+ <color name="i_am_color_19e7">#000019e7</color>
+ <color name="i_am_color_19e8">#000019e8</color>
+ <color name="i_am_color_19e9">#000019e9</color>
+ <color name="i_am_color_19ea">#000019ea</color>
+ <color name="i_am_color_19eb">#000019eb</color>
+ <color name="i_am_color_19ec">#000019ec</color>
+ <color name="i_am_color_19ed">#000019ed</color>
+ <color name="i_am_color_19ee">#000019ee</color>
+ <color name="i_am_color_19ef">#000019ef</color>
+ <color name="i_am_color_19f0">#000019f0</color>
+ <color name="i_am_color_19f1">#000019f1</color>
+ <color name="i_am_color_19f2">#000019f2</color>
+ <color name="i_am_color_19f3">#000019f3</color>
+ <color name="i_am_color_19f4">#000019f4</color>
+ <color name="i_am_color_19f5">#000019f5</color>
+ <color name="i_am_color_19f6">#000019f6</color>
+ <color name="i_am_color_19f7">#000019f7</color>
+ <color name="i_am_color_19f8">#000019f8</color>
+ <color name="i_am_color_19f9">#000019f9</color>
+ <color name="i_am_color_19fa">#000019fa</color>
+ <color name="i_am_color_19fb">#000019fb</color>
+ <color name="i_am_color_19fc">#000019fc</color>
+ <color name="i_am_color_19fd">#000019fd</color>
+ <color name="i_am_color_19fe">#000019fe</color>
+ <color name="i_am_color_19ff">#000019ff</color>
+ <color name="i_am_color_1a00">#00001a00</color>
+ <color name="i_am_color_1a01">#00001a01</color>
+ <color name="i_am_color_1a02">#00001a02</color>
+ <color name="i_am_color_1a03">#00001a03</color>
+ <color name="i_am_color_1a04">#00001a04</color>
+ <color name="i_am_color_1a05">#00001a05</color>
+ <color name="i_am_color_1a06">#00001a06</color>
+ <color name="i_am_color_1a07">#00001a07</color>
+ <color name="i_am_color_1a08">#00001a08</color>
+ <color name="i_am_color_1a09">#00001a09</color>
+ <color name="i_am_color_1a0a">#00001a0a</color>
+ <color name="i_am_color_1a0b">#00001a0b</color>
+ <color name="i_am_color_1a0c">#00001a0c</color>
+ <color name="i_am_color_1a0d">#00001a0d</color>
+ <color name="i_am_color_1a0e">#00001a0e</color>
+ <color name="i_am_color_1a0f">#00001a0f</color>
+ <color name="i_am_color_1a10">#00001a10</color>
+ <color name="i_am_color_1a11">#00001a11</color>
+ <color name="i_am_color_1a12">#00001a12</color>
+ <color name="i_am_color_1a13">#00001a13</color>
+ <color name="i_am_color_1a14">#00001a14</color>
+ <color name="i_am_color_1a15">#00001a15</color>
+ <color name="i_am_color_1a16">#00001a16</color>
+ <color name="i_am_color_1a17">#00001a17</color>
+ <color name="i_am_color_1a18">#00001a18</color>
+ <color name="i_am_color_1a19">#00001a19</color>
+ <color name="i_am_color_1a1a">#00001a1a</color>
+ <color name="i_am_color_1a1b">#00001a1b</color>
+ <color name="i_am_color_1a1c">#00001a1c</color>
+ <color name="i_am_color_1a1d">#00001a1d</color>
+ <color name="i_am_color_1a1e">#00001a1e</color>
+ <color name="i_am_color_1a1f">#00001a1f</color>
+ <color name="i_am_color_1a20">#00001a20</color>
+ <color name="i_am_color_1a21">#00001a21</color>
+ <color name="i_am_color_1a22">#00001a22</color>
+ <color name="i_am_color_1a23">#00001a23</color>
+ <color name="i_am_color_1a24">#00001a24</color>
+ <color name="i_am_color_1a25">#00001a25</color>
+ <color name="i_am_color_1a26">#00001a26</color>
+ <color name="i_am_color_1a27">#00001a27</color>
+ <color name="i_am_color_1a28">#00001a28</color>
+ <color name="i_am_color_1a29">#00001a29</color>
+ <color name="i_am_color_1a2a">#00001a2a</color>
+ <color name="i_am_color_1a2b">#00001a2b</color>
+ <color name="i_am_color_1a2c">#00001a2c</color>
+ <color name="i_am_color_1a2d">#00001a2d</color>
+ <color name="i_am_color_1a2e">#00001a2e</color>
+ <color name="i_am_color_1a2f">#00001a2f</color>
+ <color name="i_am_color_1a30">#00001a30</color>
+ <color name="i_am_color_1a31">#00001a31</color>
+ <color name="i_am_color_1a32">#00001a32</color>
+ <color name="i_am_color_1a33">#00001a33</color>
+ <color name="i_am_color_1a34">#00001a34</color>
+ <color name="i_am_color_1a35">#00001a35</color>
+ <color name="i_am_color_1a36">#00001a36</color>
+ <color name="i_am_color_1a37">#00001a37</color>
+ <color name="i_am_color_1a38">#00001a38</color>
+ <color name="i_am_color_1a39">#00001a39</color>
+ <color name="i_am_color_1a3a">#00001a3a</color>
+ <color name="i_am_color_1a3b">#00001a3b</color>
+ <color name="i_am_color_1a3c">#00001a3c</color>
+ <color name="i_am_color_1a3d">#00001a3d</color>
+ <color name="i_am_color_1a3e">#00001a3e</color>
+ <color name="i_am_color_1a3f">#00001a3f</color>
+ <color name="i_am_color_1a40">#00001a40</color>
+ <color name="i_am_color_1a41">#00001a41</color>
+ <color name="i_am_color_1a42">#00001a42</color>
+ <color name="i_am_color_1a43">#00001a43</color>
+ <color name="i_am_color_1a44">#00001a44</color>
+ <color name="i_am_color_1a45">#00001a45</color>
+ <color name="i_am_color_1a46">#00001a46</color>
+ <color name="i_am_color_1a47">#00001a47</color>
+ <color name="i_am_color_1a48">#00001a48</color>
+ <color name="i_am_color_1a49">#00001a49</color>
+ <color name="i_am_color_1a4a">#00001a4a</color>
+ <color name="i_am_color_1a4b">#00001a4b</color>
+ <color name="i_am_color_1a4c">#00001a4c</color>
+ <color name="i_am_color_1a4d">#00001a4d</color>
+ <color name="i_am_color_1a4e">#00001a4e</color>
+ <color name="i_am_color_1a4f">#00001a4f</color>
+ <color name="i_am_color_1a50">#00001a50</color>
+ <color name="i_am_color_1a51">#00001a51</color>
+ <color name="i_am_color_1a52">#00001a52</color>
+ <color name="i_am_color_1a53">#00001a53</color>
+ <color name="i_am_color_1a54">#00001a54</color>
+ <color name="i_am_color_1a55">#00001a55</color>
+ <color name="i_am_color_1a56">#00001a56</color>
+ <color name="i_am_color_1a57">#00001a57</color>
+ <color name="i_am_color_1a58">#00001a58</color>
+ <color name="i_am_color_1a59">#00001a59</color>
+ <color name="i_am_color_1a5a">#00001a5a</color>
+ <color name="i_am_color_1a5b">#00001a5b</color>
+ <color name="i_am_color_1a5c">#00001a5c</color>
+ <color name="i_am_color_1a5d">#00001a5d</color>
+ <color name="i_am_color_1a5e">#00001a5e</color>
+ <color name="i_am_color_1a5f">#00001a5f</color>
+ <color name="i_am_color_1a60">#00001a60</color>
+ <color name="i_am_color_1a61">#00001a61</color>
+ <color name="i_am_color_1a62">#00001a62</color>
+ <color name="i_am_color_1a63">#00001a63</color>
+ <color name="i_am_color_1a64">#00001a64</color>
+ <color name="i_am_color_1a65">#00001a65</color>
+ <color name="i_am_color_1a66">#00001a66</color>
+ <color name="i_am_color_1a67">#00001a67</color>
+ <color name="i_am_color_1a68">#00001a68</color>
+ <color name="i_am_color_1a69">#00001a69</color>
+ <color name="i_am_color_1a6a">#00001a6a</color>
+ <color name="i_am_color_1a6b">#00001a6b</color>
+ <color name="i_am_color_1a6c">#00001a6c</color>
+ <color name="i_am_color_1a6d">#00001a6d</color>
+ <color name="i_am_color_1a6e">#00001a6e</color>
+ <color name="i_am_color_1a6f">#00001a6f</color>
+ <color name="i_am_color_1a70">#00001a70</color>
+ <color name="i_am_color_1a71">#00001a71</color>
+ <color name="i_am_color_1a72">#00001a72</color>
+ <color name="i_am_color_1a73">#00001a73</color>
+ <color name="i_am_color_1a74">#00001a74</color>
+ <color name="i_am_color_1a75">#00001a75</color>
+ <color name="i_am_color_1a76">#00001a76</color>
+ <color name="i_am_color_1a77">#00001a77</color>
+ <color name="i_am_color_1a78">#00001a78</color>
+ <color name="i_am_color_1a79">#00001a79</color>
+ <color name="i_am_color_1a7a">#00001a7a</color>
+ <color name="i_am_color_1a7b">#00001a7b</color>
+ <color name="i_am_color_1a7c">#00001a7c</color>
+ <color name="i_am_color_1a7d">#00001a7d</color>
+ <color name="i_am_color_1a7e">#00001a7e</color>
+ <color name="i_am_color_1a7f">#00001a7f</color>
+ <color name="i_am_color_1a80">#00001a80</color>
+ <color name="i_am_color_1a81">#00001a81</color>
+ <color name="i_am_color_1a82">#00001a82</color>
+ <color name="i_am_color_1a83">#00001a83</color>
+ <color name="i_am_color_1a84">#00001a84</color>
+ <color name="i_am_color_1a85">#00001a85</color>
+ <color name="i_am_color_1a86">#00001a86</color>
+ <color name="i_am_color_1a87">#00001a87</color>
+ <color name="i_am_color_1a88">#00001a88</color>
+ <color name="i_am_color_1a89">#00001a89</color>
+ <color name="i_am_color_1a8a">#00001a8a</color>
+ <color name="i_am_color_1a8b">#00001a8b</color>
+ <color name="i_am_color_1a8c">#00001a8c</color>
+ <color name="i_am_color_1a8d">#00001a8d</color>
+ <color name="i_am_color_1a8e">#00001a8e</color>
+ <color name="i_am_color_1a8f">#00001a8f</color>
+ <color name="i_am_color_1a90">#00001a90</color>
+ <color name="i_am_color_1a91">#00001a91</color>
+ <color name="i_am_color_1a92">#00001a92</color>
+ <color name="i_am_color_1a93">#00001a93</color>
+ <color name="i_am_color_1a94">#00001a94</color>
+ <color name="i_am_color_1a95">#00001a95</color>
+ <color name="i_am_color_1a96">#00001a96</color>
+ <color name="i_am_color_1a97">#00001a97</color>
+ <color name="i_am_color_1a98">#00001a98</color>
+ <color name="i_am_color_1a99">#00001a99</color>
+ <color name="i_am_color_1a9a">#00001a9a</color>
+ <color name="i_am_color_1a9b">#00001a9b</color>
+ <color name="i_am_color_1a9c">#00001a9c</color>
+ <color name="i_am_color_1a9d">#00001a9d</color>
+ <color name="i_am_color_1a9e">#00001a9e</color>
+ <color name="i_am_color_1a9f">#00001a9f</color>
+ <color name="i_am_color_1aa0">#00001aa0</color>
+ <color name="i_am_color_1aa1">#00001aa1</color>
+ <color name="i_am_color_1aa2">#00001aa2</color>
+ <color name="i_am_color_1aa3">#00001aa3</color>
+ <color name="i_am_color_1aa4">#00001aa4</color>
+ <color name="i_am_color_1aa5">#00001aa5</color>
+ <color name="i_am_color_1aa6">#00001aa6</color>
+ <color name="i_am_color_1aa7">#00001aa7</color>
+ <color name="i_am_color_1aa8">#00001aa8</color>
+ <color name="i_am_color_1aa9">#00001aa9</color>
+ <color name="i_am_color_1aaa">#00001aaa</color>
+ <color name="i_am_color_1aab">#00001aab</color>
+ <color name="i_am_color_1aac">#00001aac</color>
+ <color name="i_am_color_1aad">#00001aad</color>
+ <color name="i_am_color_1aae">#00001aae</color>
+ <color name="i_am_color_1aaf">#00001aaf</color>
+ <color name="i_am_color_1ab0">#00001ab0</color>
+ <color name="i_am_color_1ab1">#00001ab1</color>
+ <color name="i_am_color_1ab2">#00001ab2</color>
+ <color name="i_am_color_1ab3">#00001ab3</color>
+ <color name="i_am_color_1ab4">#00001ab4</color>
+ <color name="i_am_color_1ab5">#00001ab5</color>
+ <color name="i_am_color_1ab6">#00001ab6</color>
+ <color name="i_am_color_1ab7">#00001ab7</color>
+ <color name="i_am_color_1ab8">#00001ab8</color>
+ <color name="i_am_color_1ab9">#00001ab9</color>
+ <color name="i_am_color_1aba">#00001aba</color>
+ <color name="i_am_color_1abb">#00001abb</color>
+ <color name="i_am_color_1abc">#00001abc</color>
+ <color name="i_am_color_1abd">#00001abd</color>
+ <color name="i_am_color_1abe">#00001abe</color>
+ <color name="i_am_color_1abf">#00001abf</color>
+ <color name="i_am_color_1ac0">#00001ac0</color>
+ <color name="i_am_color_1ac1">#00001ac1</color>
+ <color name="i_am_color_1ac2">#00001ac2</color>
+ <color name="i_am_color_1ac3">#00001ac3</color>
+ <color name="i_am_color_1ac4">#00001ac4</color>
+ <color name="i_am_color_1ac5">#00001ac5</color>
+ <color name="i_am_color_1ac6">#00001ac6</color>
+ <color name="i_am_color_1ac7">#00001ac7</color>
+ <color name="i_am_color_1ac8">#00001ac8</color>
+ <color name="i_am_color_1ac9">#00001ac9</color>
+ <color name="i_am_color_1aca">#00001aca</color>
+ <color name="i_am_color_1acb">#00001acb</color>
+ <color name="i_am_color_1acc">#00001acc</color>
+ <color name="i_am_color_1acd">#00001acd</color>
+ <color name="i_am_color_1ace">#00001ace</color>
+ <color name="i_am_color_1acf">#00001acf</color>
+ <color name="i_am_color_1ad0">#00001ad0</color>
+ <color name="i_am_color_1ad1">#00001ad1</color>
+ <color name="i_am_color_1ad2">#00001ad2</color>
+ <color name="i_am_color_1ad3">#00001ad3</color>
+ <color name="i_am_color_1ad4">#00001ad4</color>
+ <color name="i_am_color_1ad5">#00001ad5</color>
+ <color name="i_am_color_1ad6">#00001ad6</color>
+ <color name="i_am_color_1ad7">#00001ad7</color>
+ <color name="i_am_color_1ad8">#00001ad8</color>
+ <color name="i_am_color_1ad9">#00001ad9</color>
+ <color name="i_am_color_1ada">#00001ada</color>
+ <color name="i_am_color_1adb">#00001adb</color>
+ <color name="i_am_color_1adc">#00001adc</color>
+ <color name="i_am_color_1add">#00001add</color>
+ <color name="i_am_color_1ade">#00001ade</color>
+ <color name="i_am_color_1adf">#00001adf</color>
+ <color name="i_am_color_1ae0">#00001ae0</color>
+ <color name="i_am_color_1ae1">#00001ae1</color>
+ <color name="i_am_color_1ae2">#00001ae2</color>
+ <color name="i_am_color_1ae3">#00001ae3</color>
+ <color name="i_am_color_1ae4">#00001ae4</color>
+ <color name="i_am_color_1ae5">#00001ae5</color>
+ <color name="i_am_color_1ae6">#00001ae6</color>
+ <color name="i_am_color_1ae7">#00001ae7</color>
+ <color name="i_am_color_1ae8">#00001ae8</color>
+ <color name="i_am_color_1ae9">#00001ae9</color>
+ <color name="i_am_color_1aea">#00001aea</color>
+ <color name="i_am_color_1aeb">#00001aeb</color>
+ <color name="i_am_color_1aec">#00001aec</color>
+ <color name="i_am_color_1aed">#00001aed</color>
+ <color name="i_am_color_1aee">#00001aee</color>
+ <color name="i_am_color_1aef">#00001aef</color>
+ <color name="i_am_color_1af0">#00001af0</color>
+ <color name="i_am_color_1af1">#00001af1</color>
+ <color name="i_am_color_1af2">#00001af2</color>
+ <color name="i_am_color_1af3">#00001af3</color>
+ <color name="i_am_color_1af4">#00001af4</color>
+ <color name="i_am_color_1af5">#00001af5</color>
+ <color name="i_am_color_1af6">#00001af6</color>
+ <color name="i_am_color_1af7">#00001af7</color>
+ <color name="i_am_color_1af8">#00001af8</color>
+ <color name="i_am_color_1af9">#00001af9</color>
+ <color name="i_am_color_1afa">#00001afa</color>
+ <color name="i_am_color_1afb">#00001afb</color>
+ <color name="i_am_color_1afc">#00001afc</color>
+ <color name="i_am_color_1afd">#00001afd</color>
+ <color name="i_am_color_1afe">#00001afe</color>
+ <color name="i_am_color_1aff">#00001aff</color>
+ <color name="i_am_color_1b00">#00001b00</color>
+ <color name="i_am_color_1b01">#00001b01</color>
+ <color name="i_am_color_1b02">#00001b02</color>
+ <color name="i_am_color_1b03">#00001b03</color>
+ <color name="i_am_color_1b04">#00001b04</color>
+ <color name="i_am_color_1b05">#00001b05</color>
+ <color name="i_am_color_1b06">#00001b06</color>
+ <color name="i_am_color_1b07">#00001b07</color>
+ <color name="i_am_color_1b08">#00001b08</color>
+ <color name="i_am_color_1b09">#00001b09</color>
+ <color name="i_am_color_1b0a">#00001b0a</color>
+ <color name="i_am_color_1b0b">#00001b0b</color>
+ <color name="i_am_color_1b0c">#00001b0c</color>
+ <color name="i_am_color_1b0d">#00001b0d</color>
+ <color name="i_am_color_1b0e">#00001b0e</color>
+ <color name="i_am_color_1b0f">#00001b0f</color>
+ <color name="i_am_color_1b10">#00001b10</color>
+ <color name="i_am_color_1b11">#00001b11</color>
+ <color name="i_am_color_1b12">#00001b12</color>
+ <color name="i_am_color_1b13">#00001b13</color>
+ <color name="i_am_color_1b14">#00001b14</color>
+ <color name="i_am_color_1b15">#00001b15</color>
+ <color name="i_am_color_1b16">#00001b16</color>
+ <color name="i_am_color_1b17">#00001b17</color>
+ <color name="i_am_color_1b18">#00001b18</color>
+ <color name="i_am_color_1b19">#00001b19</color>
+ <color name="i_am_color_1b1a">#00001b1a</color>
+ <color name="i_am_color_1b1b">#00001b1b</color>
+ <color name="i_am_color_1b1c">#00001b1c</color>
+ <color name="i_am_color_1b1d">#00001b1d</color>
+ <color name="i_am_color_1b1e">#00001b1e</color>
+ <color name="i_am_color_1b1f">#00001b1f</color>
+ <color name="i_am_color_1b20">#00001b20</color>
+ <color name="i_am_color_1b21">#00001b21</color>
+ <color name="i_am_color_1b22">#00001b22</color>
+ <color name="i_am_color_1b23">#00001b23</color>
+ <color name="i_am_color_1b24">#00001b24</color>
+ <color name="i_am_color_1b25">#00001b25</color>
+ <color name="i_am_color_1b26">#00001b26</color>
+ <color name="i_am_color_1b27">#00001b27</color>
+ <color name="i_am_color_1b28">#00001b28</color>
+ <color name="i_am_color_1b29">#00001b29</color>
+ <color name="i_am_color_1b2a">#00001b2a</color>
+ <color name="i_am_color_1b2b">#00001b2b</color>
+ <color name="i_am_color_1b2c">#00001b2c</color>
+ <color name="i_am_color_1b2d">#00001b2d</color>
+ <color name="i_am_color_1b2e">#00001b2e</color>
+ <color name="i_am_color_1b2f">#00001b2f</color>
+ <color name="i_am_color_1b30">#00001b30</color>
+ <color name="i_am_color_1b31">#00001b31</color>
+ <color name="i_am_color_1b32">#00001b32</color>
+ <color name="i_am_color_1b33">#00001b33</color>
+ <color name="i_am_color_1b34">#00001b34</color>
+ <color name="i_am_color_1b35">#00001b35</color>
+ <color name="i_am_color_1b36">#00001b36</color>
+ <color name="i_am_color_1b37">#00001b37</color>
+ <color name="i_am_color_1b38">#00001b38</color>
+ <color name="i_am_color_1b39">#00001b39</color>
+ <color name="i_am_color_1b3a">#00001b3a</color>
+ <color name="i_am_color_1b3b">#00001b3b</color>
+ <color name="i_am_color_1b3c">#00001b3c</color>
+ <color name="i_am_color_1b3d">#00001b3d</color>
+ <color name="i_am_color_1b3e">#00001b3e</color>
+ <color name="i_am_color_1b3f">#00001b3f</color>
+ <color name="i_am_color_1b40">#00001b40</color>
+ <color name="i_am_color_1b41">#00001b41</color>
+ <color name="i_am_color_1b42">#00001b42</color>
+ <color name="i_am_color_1b43">#00001b43</color>
+ <color name="i_am_color_1b44">#00001b44</color>
+ <color name="i_am_color_1b45">#00001b45</color>
+ <color name="i_am_color_1b46">#00001b46</color>
+ <color name="i_am_color_1b47">#00001b47</color>
+ <color name="i_am_color_1b48">#00001b48</color>
+ <color name="i_am_color_1b49">#00001b49</color>
+ <color name="i_am_color_1b4a">#00001b4a</color>
+ <color name="i_am_color_1b4b">#00001b4b</color>
+ <color name="i_am_color_1b4c">#00001b4c</color>
+ <color name="i_am_color_1b4d">#00001b4d</color>
+ <color name="i_am_color_1b4e">#00001b4e</color>
+ <color name="i_am_color_1b4f">#00001b4f</color>
+ <color name="i_am_color_1b50">#00001b50</color>
+ <color name="i_am_color_1b51">#00001b51</color>
+ <color name="i_am_color_1b52">#00001b52</color>
+ <color name="i_am_color_1b53">#00001b53</color>
+ <color name="i_am_color_1b54">#00001b54</color>
+ <color name="i_am_color_1b55">#00001b55</color>
+ <color name="i_am_color_1b56">#00001b56</color>
+ <color name="i_am_color_1b57">#00001b57</color>
+ <color name="i_am_color_1b58">#00001b58</color>
+ <color name="i_am_color_1b59">#00001b59</color>
+ <color name="i_am_color_1b5a">#00001b5a</color>
+ <color name="i_am_color_1b5b">#00001b5b</color>
+ <color name="i_am_color_1b5c">#00001b5c</color>
+ <color name="i_am_color_1b5d">#00001b5d</color>
+ <color name="i_am_color_1b5e">#00001b5e</color>
+ <color name="i_am_color_1b5f">#00001b5f</color>
+ <color name="i_am_color_1b60">#00001b60</color>
+ <color name="i_am_color_1b61">#00001b61</color>
+ <color name="i_am_color_1b62">#00001b62</color>
+ <color name="i_am_color_1b63">#00001b63</color>
+ <color name="i_am_color_1b64">#00001b64</color>
+ <color name="i_am_color_1b65">#00001b65</color>
+ <color name="i_am_color_1b66">#00001b66</color>
+ <color name="i_am_color_1b67">#00001b67</color>
+ <color name="i_am_color_1b68">#00001b68</color>
+ <color name="i_am_color_1b69">#00001b69</color>
+ <color name="i_am_color_1b6a">#00001b6a</color>
+ <color name="i_am_color_1b6b">#00001b6b</color>
+ <color name="i_am_color_1b6c">#00001b6c</color>
+ <color name="i_am_color_1b6d">#00001b6d</color>
+ <color name="i_am_color_1b6e">#00001b6e</color>
+ <color name="i_am_color_1b6f">#00001b6f</color>
+ <color name="i_am_color_1b70">#00001b70</color>
+ <color name="i_am_color_1b71">#00001b71</color>
+ <color name="i_am_color_1b72">#00001b72</color>
+ <color name="i_am_color_1b73">#00001b73</color>
+ <color name="i_am_color_1b74">#00001b74</color>
+ <color name="i_am_color_1b75">#00001b75</color>
+ <color name="i_am_color_1b76">#00001b76</color>
+ <color name="i_am_color_1b77">#00001b77</color>
+ <color name="i_am_color_1b78">#00001b78</color>
+ <color name="i_am_color_1b79">#00001b79</color>
+ <color name="i_am_color_1b7a">#00001b7a</color>
+ <color name="i_am_color_1b7b">#00001b7b</color>
+ <color name="i_am_color_1b7c">#00001b7c</color>
+ <color name="i_am_color_1b7d">#00001b7d</color>
+ <color name="i_am_color_1b7e">#00001b7e</color>
+ <color name="i_am_color_1b7f">#00001b7f</color>
+ <color name="i_am_color_1b80">#00001b80</color>
+ <color name="i_am_color_1b81">#00001b81</color>
+ <color name="i_am_color_1b82">#00001b82</color>
+ <color name="i_am_color_1b83">#00001b83</color>
+ <color name="i_am_color_1b84">#00001b84</color>
+ <color name="i_am_color_1b85">#00001b85</color>
+ <color name="i_am_color_1b86">#00001b86</color>
+ <color name="i_am_color_1b87">#00001b87</color>
+ <color name="i_am_color_1b88">#00001b88</color>
+ <color name="i_am_color_1b89">#00001b89</color>
+ <color name="i_am_color_1b8a">#00001b8a</color>
+ <color name="i_am_color_1b8b">#00001b8b</color>
+ <color name="i_am_color_1b8c">#00001b8c</color>
+ <color name="i_am_color_1b8d">#00001b8d</color>
+ <color name="i_am_color_1b8e">#00001b8e</color>
+ <color name="i_am_color_1b8f">#00001b8f</color>
+ <color name="i_am_color_1b90">#00001b90</color>
+ <color name="i_am_color_1b91">#00001b91</color>
+ <color name="i_am_color_1b92">#00001b92</color>
+ <color name="i_am_color_1b93">#00001b93</color>
+ <color name="i_am_color_1b94">#00001b94</color>
+ <color name="i_am_color_1b95">#00001b95</color>
+ <color name="i_am_color_1b96">#00001b96</color>
+ <color name="i_am_color_1b97">#00001b97</color>
+ <color name="i_am_color_1b98">#00001b98</color>
+ <color name="i_am_color_1b99">#00001b99</color>
+ <color name="i_am_color_1b9a">#00001b9a</color>
+ <color name="i_am_color_1b9b">#00001b9b</color>
+ <color name="i_am_color_1b9c">#00001b9c</color>
+ <color name="i_am_color_1b9d">#00001b9d</color>
+ <color name="i_am_color_1b9e">#00001b9e</color>
+ <color name="i_am_color_1b9f">#00001b9f</color>
+ <color name="i_am_color_1ba0">#00001ba0</color>
+ <color name="i_am_color_1ba1">#00001ba1</color>
+ <color name="i_am_color_1ba2">#00001ba2</color>
+ <color name="i_am_color_1ba3">#00001ba3</color>
+ <color name="i_am_color_1ba4">#00001ba4</color>
+ <color name="i_am_color_1ba5">#00001ba5</color>
+ <color name="i_am_color_1ba6">#00001ba6</color>
+ <color name="i_am_color_1ba7">#00001ba7</color>
+ <color name="i_am_color_1ba8">#00001ba8</color>
+ <color name="i_am_color_1ba9">#00001ba9</color>
+ <color name="i_am_color_1baa">#00001baa</color>
+ <color name="i_am_color_1bab">#00001bab</color>
+ <color name="i_am_color_1bac">#00001bac</color>
+ <color name="i_am_color_1bad">#00001bad</color>
+ <color name="i_am_color_1bae">#00001bae</color>
+ <color name="i_am_color_1baf">#00001baf</color>
+ <color name="i_am_color_1bb0">#00001bb0</color>
+ <color name="i_am_color_1bb1">#00001bb1</color>
+ <color name="i_am_color_1bb2">#00001bb2</color>
+ <color name="i_am_color_1bb3">#00001bb3</color>
+ <color name="i_am_color_1bb4">#00001bb4</color>
+ <color name="i_am_color_1bb5">#00001bb5</color>
+ <color name="i_am_color_1bb6">#00001bb6</color>
+ <color name="i_am_color_1bb7">#00001bb7</color>
+ <color name="i_am_color_1bb8">#00001bb8</color>
+ <color name="i_am_color_1bb9">#00001bb9</color>
+ <color name="i_am_color_1bba">#00001bba</color>
+ <color name="i_am_color_1bbb">#00001bbb</color>
+ <color name="i_am_color_1bbc">#00001bbc</color>
+ <color name="i_am_color_1bbd">#00001bbd</color>
+ <color name="i_am_color_1bbe">#00001bbe</color>
+ <color name="i_am_color_1bbf">#00001bbf</color>
+ <color name="i_am_color_1bc0">#00001bc0</color>
+ <color name="i_am_color_1bc1">#00001bc1</color>
+ <color name="i_am_color_1bc2">#00001bc2</color>
+ <color name="i_am_color_1bc3">#00001bc3</color>
+ <color name="i_am_color_1bc4">#00001bc4</color>
+ <color name="i_am_color_1bc5">#00001bc5</color>
+ <color name="i_am_color_1bc6">#00001bc6</color>
+ <color name="i_am_color_1bc7">#00001bc7</color>
+ <color name="i_am_color_1bc8">#00001bc8</color>
+ <color name="i_am_color_1bc9">#00001bc9</color>
+ <color name="i_am_color_1bca">#00001bca</color>
+ <color name="i_am_color_1bcb">#00001bcb</color>
+ <color name="i_am_color_1bcc">#00001bcc</color>
+ <color name="i_am_color_1bcd">#00001bcd</color>
+ <color name="i_am_color_1bce">#00001bce</color>
+ <color name="i_am_color_1bcf">#00001bcf</color>
+ <color name="i_am_color_1bd0">#00001bd0</color>
+ <color name="i_am_color_1bd1">#00001bd1</color>
+ <color name="i_am_color_1bd2">#00001bd2</color>
+ <color name="i_am_color_1bd3">#00001bd3</color>
+ <color name="i_am_color_1bd4">#00001bd4</color>
+ <color name="i_am_color_1bd5">#00001bd5</color>
+ <color name="i_am_color_1bd6">#00001bd6</color>
+ <color name="i_am_color_1bd7">#00001bd7</color>
+ <color name="i_am_color_1bd8">#00001bd8</color>
+ <color name="i_am_color_1bd9">#00001bd9</color>
+ <color name="i_am_color_1bda">#00001bda</color>
+ <color name="i_am_color_1bdb">#00001bdb</color>
+ <color name="i_am_color_1bdc">#00001bdc</color>
+ <color name="i_am_color_1bdd">#00001bdd</color>
+ <color name="i_am_color_1bde">#00001bde</color>
+ <color name="i_am_color_1bdf">#00001bdf</color>
+ <color name="i_am_color_1be0">#00001be0</color>
+ <color name="i_am_color_1be1">#00001be1</color>
+ <color name="i_am_color_1be2">#00001be2</color>
+ <color name="i_am_color_1be3">#00001be3</color>
+ <color name="i_am_color_1be4">#00001be4</color>
+ <color name="i_am_color_1be5">#00001be5</color>
+ <color name="i_am_color_1be6">#00001be6</color>
+ <color name="i_am_color_1be7">#00001be7</color>
+ <color name="i_am_color_1be8">#00001be8</color>
+ <color name="i_am_color_1be9">#00001be9</color>
+ <color name="i_am_color_1bea">#00001bea</color>
+ <color name="i_am_color_1beb">#00001beb</color>
+ <color name="i_am_color_1bec">#00001bec</color>
+ <color name="i_am_color_1bed">#00001bed</color>
+ <color name="i_am_color_1bee">#00001bee</color>
+ <color name="i_am_color_1bef">#00001bef</color>
+ <color name="i_am_color_1bf0">#00001bf0</color>
+ <color name="i_am_color_1bf1">#00001bf1</color>
+ <color name="i_am_color_1bf2">#00001bf2</color>
+ <color name="i_am_color_1bf3">#00001bf3</color>
+ <color name="i_am_color_1bf4">#00001bf4</color>
+ <color name="i_am_color_1bf5">#00001bf5</color>
+ <color name="i_am_color_1bf6">#00001bf6</color>
+ <color name="i_am_color_1bf7">#00001bf7</color>
+ <color name="i_am_color_1bf8">#00001bf8</color>
+ <color name="i_am_color_1bf9">#00001bf9</color>
+ <color name="i_am_color_1bfa">#00001bfa</color>
+ <color name="i_am_color_1bfb">#00001bfb</color>
+ <color name="i_am_color_1bfc">#00001bfc</color>
+ <color name="i_am_color_1bfd">#00001bfd</color>
+ <color name="i_am_color_1bfe">#00001bfe</color>
+ <color name="i_am_color_1bff">#00001bff</color>
+ <color name="i_am_color_1c00">#00001c00</color>
+ <color name="i_am_color_1c01">#00001c01</color>
+ <color name="i_am_color_1c02">#00001c02</color>
+ <color name="i_am_color_1c03">#00001c03</color>
+ <color name="i_am_color_1c04">#00001c04</color>
+ <color name="i_am_color_1c05">#00001c05</color>
+ <color name="i_am_color_1c06">#00001c06</color>
+ <color name="i_am_color_1c07">#00001c07</color>
+ <color name="i_am_color_1c08">#00001c08</color>
+ <color name="i_am_color_1c09">#00001c09</color>
+ <color name="i_am_color_1c0a">#00001c0a</color>
+ <color name="i_am_color_1c0b">#00001c0b</color>
+ <color name="i_am_color_1c0c">#00001c0c</color>
+ <color name="i_am_color_1c0d">#00001c0d</color>
+ <color name="i_am_color_1c0e">#00001c0e</color>
+ <color name="i_am_color_1c0f">#00001c0f</color>
+ <color name="i_am_color_1c10">#00001c10</color>
+ <color name="i_am_color_1c11">#00001c11</color>
+ <color name="i_am_color_1c12">#00001c12</color>
+ <color name="i_am_color_1c13">#00001c13</color>
+ <color name="i_am_color_1c14">#00001c14</color>
+ <color name="i_am_color_1c15">#00001c15</color>
+ <color name="i_am_color_1c16">#00001c16</color>
+ <color name="i_am_color_1c17">#00001c17</color>
+ <color name="i_am_color_1c18">#00001c18</color>
+ <color name="i_am_color_1c19">#00001c19</color>
+ <color name="i_am_color_1c1a">#00001c1a</color>
+ <color name="i_am_color_1c1b">#00001c1b</color>
+ <color name="i_am_color_1c1c">#00001c1c</color>
+ <color name="i_am_color_1c1d">#00001c1d</color>
+ <color name="i_am_color_1c1e">#00001c1e</color>
+ <color name="i_am_color_1c1f">#00001c1f</color>
+ <color name="i_am_color_1c20">#00001c20</color>
+ <color name="i_am_color_1c21">#00001c21</color>
+ <color name="i_am_color_1c22">#00001c22</color>
+ <color name="i_am_color_1c23">#00001c23</color>
+ <color name="i_am_color_1c24">#00001c24</color>
+ <color name="i_am_color_1c25">#00001c25</color>
+ <color name="i_am_color_1c26">#00001c26</color>
+ <color name="i_am_color_1c27">#00001c27</color>
+ <color name="i_am_color_1c28">#00001c28</color>
+ <color name="i_am_color_1c29">#00001c29</color>
+ <color name="i_am_color_1c2a">#00001c2a</color>
+ <color name="i_am_color_1c2b">#00001c2b</color>
+ <color name="i_am_color_1c2c">#00001c2c</color>
+ <color name="i_am_color_1c2d">#00001c2d</color>
+ <color name="i_am_color_1c2e">#00001c2e</color>
+ <color name="i_am_color_1c2f">#00001c2f</color>
+ <color name="i_am_color_1c30">#00001c30</color>
+ <color name="i_am_color_1c31">#00001c31</color>
+ <color name="i_am_color_1c32">#00001c32</color>
+ <color name="i_am_color_1c33">#00001c33</color>
+ <color name="i_am_color_1c34">#00001c34</color>
+ <color name="i_am_color_1c35">#00001c35</color>
+ <color name="i_am_color_1c36">#00001c36</color>
+ <color name="i_am_color_1c37">#00001c37</color>
+ <color name="i_am_color_1c38">#00001c38</color>
+ <color name="i_am_color_1c39">#00001c39</color>
+ <color name="i_am_color_1c3a">#00001c3a</color>
+ <color name="i_am_color_1c3b">#00001c3b</color>
+ <color name="i_am_color_1c3c">#00001c3c</color>
+ <color name="i_am_color_1c3d">#00001c3d</color>
+ <color name="i_am_color_1c3e">#00001c3e</color>
+ <color name="i_am_color_1c3f">#00001c3f</color>
+ <color name="i_am_color_1c40">#00001c40</color>
+ <color name="i_am_color_1c41">#00001c41</color>
+ <color name="i_am_color_1c42">#00001c42</color>
+ <color name="i_am_color_1c43">#00001c43</color>
+ <color name="i_am_color_1c44">#00001c44</color>
+ <color name="i_am_color_1c45">#00001c45</color>
+ <color name="i_am_color_1c46">#00001c46</color>
+ <color name="i_am_color_1c47">#00001c47</color>
+ <color name="i_am_color_1c48">#00001c48</color>
+ <color name="i_am_color_1c49">#00001c49</color>
+ <color name="i_am_color_1c4a">#00001c4a</color>
+ <color name="i_am_color_1c4b">#00001c4b</color>
+ <color name="i_am_color_1c4c">#00001c4c</color>
+ <color name="i_am_color_1c4d">#00001c4d</color>
+ <color name="i_am_color_1c4e">#00001c4e</color>
+ <color name="i_am_color_1c4f">#00001c4f</color>
+ <color name="i_am_color_1c50">#00001c50</color>
+ <color name="i_am_color_1c51">#00001c51</color>
+ <color name="i_am_color_1c52">#00001c52</color>
+ <color name="i_am_color_1c53">#00001c53</color>
+ <color name="i_am_color_1c54">#00001c54</color>
+ <color name="i_am_color_1c55">#00001c55</color>
+ <color name="i_am_color_1c56">#00001c56</color>
+ <color name="i_am_color_1c57">#00001c57</color>
+ <color name="i_am_color_1c58">#00001c58</color>
+ <color name="i_am_color_1c59">#00001c59</color>
+ <color name="i_am_color_1c5a">#00001c5a</color>
+ <color name="i_am_color_1c5b">#00001c5b</color>
+ <color name="i_am_color_1c5c">#00001c5c</color>
+ <color name="i_am_color_1c5d">#00001c5d</color>
+ <color name="i_am_color_1c5e">#00001c5e</color>
+ <color name="i_am_color_1c5f">#00001c5f</color>
+ <color name="i_am_color_1c60">#00001c60</color>
+ <color name="i_am_color_1c61">#00001c61</color>
+ <color name="i_am_color_1c62">#00001c62</color>
+ <color name="i_am_color_1c63">#00001c63</color>
+ <color name="i_am_color_1c64">#00001c64</color>
+ <color name="i_am_color_1c65">#00001c65</color>
+ <color name="i_am_color_1c66">#00001c66</color>
+ <color name="i_am_color_1c67">#00001c67</color>
+ <color name="i_am_color_1c68">#00001c68</color>
+ <color name="i_am_color_1c69">#00001c69</color>
+ <color name="i_am_color_1c6a">#00001c6a</color>
+ <color name="i_am_color_1c6b">#00001c6b</color>
+ <color name="i_am_color_1c6c">#00001c6c</color>
+ <color name="i_am_color_1c6d">#00001c6d</color>
+ <color name="i_am_color_1c6e">#00001c6e</color>
+ <color name="i_am_color_1c6f">#00001c6f</color>
+ <color name="i_am_color_1c70">#00001c70</color>
+ <color name="i_am_color_1c71">#00001c71</color>
+ <color name="i_am_color_1c72">#00001c72</color>
+ <color name="i_am_color_1c73">#00001c73</color>
+ <color name="i_am_color_1c74">#00001c74</color>
+ <color name="i_am_color_1c75">#00001c75</color>
+ <color name="i_am_color_1c76">#00001c76</color>
+ <color name="i_am_color_1c77">#00001c77</color>
+ <color name="i_am_color_1c78">#00001c78</color>
+ <color name="i_am_color_1c79">#00001c79</color>
+ <color name="i_am_color_1c7a">#00001c7a</color>
+ <color name="i_am_color_1c7b">#00001c7b</color>
+ <color name="i_am_color_1c7c">#00001c7c</color>
+ <color name="i_am_color_1c7d">#00001c7d</color>
+ <color name="i_am_color_1c7e">#00001c7e</color>
+ <color name="i_am_color_1c7f">#00001c7f</color>
+ <color name="i_am_color_1c80">#00001c80</color>
+ <color name="i_am_color_1c81">#00001c81</color>
+ <color name="i_am_color_1c82">#00001c82</color>
+ <color name="i_am_color_1c83">#00001c83</color>
+ <color name="i_am_color_1c84">#00001c84</color>
+ <color name="i_am_color_1c85">#00001c85</color>
+ <color name="i_am_color_1c86">#00001c86</color>
+ <color name="i_am_color_1c87">#00001c87</color>
+ <color name="i_am_color_1c88">#00001c88</color>
+ <color name="i_am_color_1c89">#00001c89</color>
+ <color name="i_am_color_1c8a">#00001c8a</color>
+ <color name="i_am_color_1c8b">#00001c8b</color>
+ <color name="i_am_color_1c8c">#00001c8c</color>
+ <color name="i_am_color_1c8d">#00001c8d</color>
+ <color name="i_am_color_1c8e">#00001c8e</color>
+ <color name="i_am_color_1c8f">#00001c8f</color>
+ <color name="i_am_color_1c90">#00001c90</color>
+ <color name="i_am_color_1c91">#00001c91</color>
+ <color name="i_am_color_1c92">#00001c92</color>
+ <color name="i_am_color_1c93">#00001c93</color>
+ <color name="i_am_color_1c94">#00001c94</color>
+ <color name="i_am_color_1c95">#00001c95</color>
+ <color name="i_am_color_1c96">#00001c96</color>
+ <color name="i_am_color_1c97">#00001c97</color>
+ <color name="i_am_color_1c98">#00001c98</color>
+ <color name="i_am_color_1c99">#00001c99</color>
+ <color name="i_am_color_1c9a">#00001c9a</color>
+ <color name="i_am_color_1c9b">#00001c9b</color>
+ <color name="i_am_color_1c9c">#00001c9c</color>
+ <color name="i_am_color_1c9d">#00001c9d</color>
+ <color name="i_am_color_1c9e">#00001c9e</color>
+ <color name="i_am_color_1c9f">#00001c9f</color>
+ <color name="i_am_color_1ca0">#00001ca0</color>
+ <color name="i_am_color_1ca1">#00001ca1</color>
+ <color name="i_am_color_1ca2">#00001ca2</color>
+ <color name="i_am_color_1ca3">#00001ca3</color>
+ <color name="i_am_color_1ca4">#00001ca4</color>
+ <color name="i_am_color_1ca5">#00001ca5</color>
+ <color name="i_am_color_1ca6">#00001ca6</color>
+ <color name="i_am_color_1ca7">#00001ca7</color>
+ <color name="i_am_color_1ca8">#00001ca8</color>
+ <color name="i_am_color_1ca9">#00001ca9</color>
+ <color name="i_am_color_1caa">#00001caa</color>
+ <color name="i_am_color_1cab">#00001cab</color>
+ <color name="i_am_color_1cac">#00001cac</color>
+ <color name="i_am_color_1cad">#00001cad</color>
+ <color name="i_am_color_1cae">#00001cae</color>
+ <color name="i_am_color_1caf">#00001caf</color>
+ <color name="i_am_color_1cb0">#00001cb0</color>
+ <color name="i_am_color_1cb1">#00001cb1</color>
+ <color name="i_am_color_1cb2">#00001cb2</color>
+ <color name="i_am_color_1cb3">#00001cb3</color>
+ <color name="i_am_color_1cb4">#00001cb4</color>
+ <color name="i_am_color_1cb5">#00001cb5</color>
+ <color name="i_am_color_1cb6">#00001cb6</color>
+ <color name="i_am_color_1cb7">#00001cb7</color>
+ <color name="i_am_color_1cb8">#00001cb8</color>
+ <color name="i_am_color_1cb9">#00001cb9</color>
+ <color name="i_am_color_1cba">#00001cba</color>
+ <color name="i_am_color_1cbb">#00001cbb</color>
+ <color name="i_am_color_1cbc">#00001cbc</color>
+ <color name="i_am_color_1cbd">#00001cbd</color>
+ <color name="i_am_color_1cbe">#00001cbe</color>
+ <color name="i_am_color_1cbf">#00001cbf</color>
+ <color name="i_am_color_1cc0">#00001cc0</color>
+ <color name="i_am_color_1cc1">#00001cc1</color>
+ <color name="i_am_color_1cc2">#00001cc2</color>
+ <color name="i_am_color_1cc3">#00001cc3</color>
+ <color name="i_am_color_1cc4">#00001cc4</color>
+ <color name="i_am_color_1cc5">#00001cc5</color>
+ <color name="i_am_color_1cc6">#00001cc6</color>
+ <color name="i_am_color_1cc7">#00001cc7</color>
+ <color name="i_am_color_1cc8">#00001cc8</color>
+ <color name="i_am_color_1cc9">#00001cc9</color>
+ <color name="i_am_color_1cca">#00001cca</color>
+ <color name="i_am_color_1ccb">#00001ccb</color>
+ <color name="i_am_color_1ccc">#00001ccc</color>
+ <color name="i_am_color_1ccd">#00001ccd</color>
+ <color name="i_am_color_1cce">#00001cce</color>
+ <color name="i_am_color_1ccf">#00001ccf</color>
+ <color name="i_am_color_1cd0">#00001cd0</color>
+ <color name="i_am_color_1cd1">#00001cd1</color>
+ <color name="i_am_color_1cd2">#00001cd2</color>
+ <color name="i_am_color_1cd3">#00001cd3</color>
+ <color name="i_am_color_1cd4">#00001cd4</color>
+ <color name="i_am_color_1cd5">#00001cd5</color>
+ <color name="i_am_color_1cd6">#00001cd6</color>
+ <color name="i_am_color_1cd7">#00001cd7</color>
+ <color name="i_am_color_1cd8">#00001cd8</color>
+ <color name="i_am_color_1cd9">#00001cd9</color>
+ <color name="i_am_color_1cda">#00001cda</color>
+ <color name="i_am_color_1cdb">#00001cdb</color>
+ <color name="i_am_color_1cdc">#00001cdc</color>
+ <color name="i_am_color_1cdd">#00001cdd</color>
+ <color name="i_am_color_1cde">#00001cde</color>
+ <color name="i_am_color_1cdf">#00001cdf</color>
+ <color name="i_am_color_1ce0">#00001ce0</color>
+ <color name="i_am_color_1ce1">#00001ce1</color>
+ <color name="i_am_color_1ce2">#00001ce2</color>
+ <color name="i_am_color_1ce3">#00001ce3</color>
+ <color name="i_am_color_1ce4">#00001ce4</color>
+ <color name="i_am_color_1ce5">#00001ce5</color>
+ <color name="i_am_color_1ce6">#00001ce6</color>
+ <color name="i_am_color_1ce7">#00001ce7</color>
+ <color name="i_am_color_1ce8">#00001ce8</color>
+ <color name="i_am_color_1ce9">#00001ce9</color>
+ <color name="i_am_color_1cea">#00001cea</color>
+ <color name="i_am_color_1ceb">#00001ceb</color>
+ <color name="i_am_color_1cec">#00001cec</color>
+ <color name="i_am_color_1ced">#00001ced</color>
+ <color name="i_am_color_1cee">#00001cee</color>
+ <color name="i_am_color_1cef">#00001cef</color>
+ <color name="i_am_color_1cf0">#00001cf0</color>
+ <color name="i_am_color_1cf1">#00001cf1</color>
+ <color name="i_am_color_1cf2">#00001cf2</color>
+ <color name="i_am_color_1cf3">#00001cf3</color>
+ <color name="i_am_color_1cf4">#00001cf4</color>
+ <color name="i_am_color_1cf5">#00001cf5</color>
+ <color name="i_am_color_1cf6">#00001cf6</color>
+ <color name="i_am_color_1cf7">#00001cf7</color>
+ <color name="i_am_color_1cf8">#00001cf8</color>
+ <color name="i_am_color_1cf9">#00001cf9</color>
+ <color name="i_am_color_1cfa">#00001cfa</color>
+ <color name="i_am_color_1cfb">#00001cfb</color>
+ <color name="i_am_color_1cfc">#00001cfc</color>
+ <color name="i_am_color_1cfd">#00001cfd</color>
+ <color name="i_am_color_1cfe">#00001cfe</color>
+ <color name="i_am_color_1cff">#00001cff</color>
+ <color name="i_am_color_1d00">#00001d00</color>
+ <color name="i_am_color_1d01">#00001d01</color>
+ <color name="i_am_color_1d02">#00001d02</color>
+ <color name="i_am_color_1d03">#00001d03</color>
+ <color name="i_am_color_1d04">#00001d04</color>
+ <color name="i_am_color_1d05">#00001d05</color>
+ <color name="i_am_color_1d06">#00001d06</color>
+ <color name="i_am_color_1d07">#00001d07</color>
+ <color name="i_am_color_1d08">#00001d08</color>
+ <color name="i_am_color_1d09">#00001d09</color>
+ <color name="i_am_color_1d0a">#00001d0a</color>
+ <color name="i_am_color_1d0b">#00001d0b</color>
+ <color name="i_am_color_1d0c">#00001d0c</color>
+ <color name="i_am_color_1d0d">#00001d0d</color>
+ <color name="i_am_color_1d0e">#00001d0e</color>
+ <color name="i_am_color_1d0f">#00001d0f</color>
+ <color name="i_am_color_1d10">#00001d10</color>
+ <color name="i_am_color_1d11">#00001d11</color>
+ <color name="i_am_color_1d12">#00001d12</color>
+ <color name="i_am_color_1d13">#00001d13</color>
+ <color name="i_am_color_1d14">#00001d14</color>
+ <color name="i_am_color_1d15">#00001d15</color>
+ <color name="i_am_color_1d16">#00001d16</color>
+ <color name="i_am_color_1d17">#00001d17</color>
+ <color name="i_am_color_1d18">#00001d18</color>
+ <color name="i_am_color_1d19">#00001d19</color>
+ <color name="i_am_color_1d1a">#00001d1a</color>
+ <color name="i_am_color_1d1b">#00001d1b</color>
+ <color name="i_am_color_1d1c">#00001d1c</color>
+ <color name="i_am_color_1d1d">#00001d1d</color>
+ <color name="i_am_color_1d1e">#00001d1e</color>
+ <color name="i_am_color_1d1f">#00001d1f</color>
+ <color name="i_am_color_1d20">#00001d20</color>
+ <color name="i_am_color_1d21">#00001d21</color>
+ <color name="i_am_color_1d22">#00001d22</color>
+ <color name="i_am_color_1d23">#00001d23</color>
+ <color name="i_am_color_1d24">#00001d24</color>
+ <color name="i_am_color_1d25">#00001d25</color>
+ <color name="i_am_color_1d26">#00001d26</color>
+ <color name="i_am_color_1d27">#00001d27</color>
+ <color name="i_am_color_1d28">#00001d28</color>
+ <color name="i_am_color_1d29">#00001d29</color>
+ <color name="i_am_color_1d2a">#00001d2a</color>
+ <color name="i_am_color_1d2b">#00001d2b</color>
+ <color name="i_am_color_1d2c">#00001d2c</color>
+ <color name="i_am_color_1d2d">#00001d2d</color>
+ <color name="i_am_color_1d2e">#00001d2e</color>
+ <color name="i_am_color_1d2f">#00001d2f</color>
+ <color name="i_am_color_1d30">#00001d30</color>
+ <color name="i_am_color_1d31">#00001d31</color>
+ <color name="i_am_color_1d32">#00001d32</color>
+ <color name="i_am_color_1d33">#00001d33</color>
+ <color name="i_am_color_1d34">#00001d34</color>
+ <color name="i_am_color_1d35">#00001d35</color>
+ <color name="i_am_color_1d36">#00001d36</color>
+ <color name="i_am_color_1d37">#00001d37</color>
+ <color name="i_am_color_1d38">#00001d38</color>
+ <color name="i_am_color_1d39">#00001d39</color>
+ <color name="i_am_color_1d3a">#00001d3a</color>
+ <color name="i_am_color_1d3b">#00001d3b</color>
+ <color name="i_am_color_1d3c">#00001d3c</color>
+ <color name="i_am_color_1d3d">#00001d3d</color>
+ <color name="i_am_color_1d3e">#00001d3e</color>
+ <color name="i_am_color_1d3f">#00001d3f</color>
+ <color name="i_am_color_1d40">#00001d40</color>
+ <color name="i_am_color_1d41">#00001d41</color>
+ <color name="i_am_color_1d42">#00001d42</color>
+ <color name="i_am_color_1d43">#00001d43</color>
+ <color name="i_am_color_1d44">#00001d44</color>
+ <color name="i_am_color_1d45">#00001d45</color>
+ <color name="i_am_color_1d46">#00001d46</color>
+ <color name="i_am_color_1d47">#00001d47</color>
+ <color name="i_am_color_1d48">#00001d48</color>
+ <color name="i_am_color_1d49">#00001d49</color>
+ <color name="i_am_color_1d4a">#00001d4a</color>
+ <color name="i_am_color_1d4b">#00001d4b</color>
+ <color name="i_am_color_1d4c">#00001d4c</color>
+ <color name="i_am_color_1d4d">#00001d4d</color>
+ <color name="i_am_color_1d4e">#00001d4e</color>
+ <color name="i_am_color_1d4f">#00001d4f</color>
+ <color name="i_am_color_1d50">#00001d50</color>
+ <color name="i_am_color_1d51">#00001d51</color>
+ <color name="i_am_color_1d52">#00001d52</color>
+ <color name="i_am_color_1d53">#00001d53</color>
+ <color name="i_am_color_1d54">#00001d54</color>
+ <color name="i_am_color_1d55">#00001d55</color>
+ <color name="i_am_color_1d56">#00001d56</color>
+ <color name="i_am_color_1d57">#00001d57</color>
+ <color name="i_am_color_1d58">#00001d58</color>
+ <color name="i_am_color_1d59">#00001d59</color>
+ <color name="i_am_color_1d5a">#00001d5a</color>
+ <color name="i_am_color_1d5b">#00001d5b</color>
+ <color name="i_am_color_1d5c">#00001d5c</color>
+ <color name="i_am_color_1d5d">#00001d5d</color>
+ <color name="i_am_color_1d5e">#00001d5e</color>
+ <color name="i_am_color_1d5f">#00001d5f</color>
+ <color name="i_am_color_1d60">#00001d60</color>
+ <color name="i_am_color_1d61">#00001d61</color>
+ <color name="i_am_color_1d62">#00001d62</color>
+ <color name="i_am_color_1d63">#00001d63</color>
+ <color name="i_am_color_1d64">#00001d64</color>
+ <color name="i_am_color_1d65">#00001d65</color>
+ <color name="i_am_color_1d66">#00001d66</color>
+ <color name="i_am_color_1d67">#00001d67</color>
+ <color name="i_am_color_1d68">#00001d68</color>
+ <color name="i_am_color_1d69">#00001d69</color>
+ <color name="i_am_color_1d6a">#00001d6a</color>
+ <color name="i_am_color_1d6b">#00001d6b</color>
+ <color name="i_am_color_1d6c">#00001d6c</color>
+ <color name="i_am_color_1d6d">#00001d6d</color>
+ <color name="i_am_color_1d6e">#00001d6e</color>
+ <color name="i_am_color_1d6f">#00001d6f</color>
+ <color name="i_am_color_1d70">#00001d70</color>
+ <color name="i_am_color_1d71">#00001d71</color>
+ <color name="i_am_color_1d72">#00001d72</color>
+ <color name="i_am_color_1d73">#00001d73</color>
+ <color name="i_am_color_1d74">#00001d74</color>
+ <color name="i_am_color_1d75">#00001d75</color>
+ <color name="i_am_color_1d76">#00001d76</color>
+ <color name="i_am_color_1d77">#00001d77</color>
+ <color name="i_am_color_1d78">#00001d78</color>
+ <color name="i_am_color_1d79">#00001d79</color>
+ <color name="i_am_color_1d7a">#00001d7a</color>
+ <color name="i_am_color_1d7b">#00001d7b</color>
+ <color name="i_am_color_1d7c">#00001d7c</color>
+ <color name="i_am_color_1d7d">#00001d7d</color>
+ <color name="i_am_color_1d7e">#00001d7e</color>
+ <color name="i_am_color_1d7f">#00001d7f</color>
+ <color name="i_am_color_1d80">#00001d80</color>
+ <color name="i_am_color_1d81">#00001d81</color>
+ <color name="i_am_color_1d82">#00001d82</color>
+ <color name="i_am_color_1d83">#00001d83</color>
+ <color name="i_am_color_1d84">#00001d84</color>
+ <color name="i_am_color_1d85">#00001d85</color>
+ <color name="i_am_color_1d86">#00001d86</color>
+ <color name="i_am_color_1d87">#00001d87</color>
+ <color name="i_am_color_1d88">#00001d88</color>
+ <color name="i_am_color_1d89">#00001d89</color>
+ <color name="i_am_color_1d8a">#00001d8a</color>
+ <color name="i_am_color_1d8b">#00001d8b</color>
+ <color name="i_am_color_1d8c">#00001d8c</color>
+ <color name="i_am_color_1d8d">#00001d8d</color>
+ <color name="i_am_color_1d8e">#00001d8e</color>
+ <color name="i_am_color_1d8f">#00001d8f</color>
+ <color name="i_am_color_1d90">#00001d90</color>
+ <color name="i_am_color_1d91">#00001d91</color>
+ <color name="i_am_color_1d92">#00001d92</color>
+ <color name="i_am_color_1d93">#00001d93</color>
+ <color name="i_am_color_1d94">#00001d94</color>
+ <color name="i_am_color_1d95">#00001d95</color>
+ <color name="i_am_color_1d96">#00001d96</color>
+ <color name="i_am_color_1d97">#00001d97</color>
+ <color name="i_am_color_1d98">#00001d98</color>
+ <color name="i_am_color_1d99">#00001d99</color>
+ <color name="i_am_color_1d9a">#00001d9a</color>
+ <color name="i_am_color_1d9b">#00001d9b</color>
+ <color name="i_am_color_1d9c">#00001d9c</color>
+ <color name="i_am_color_1d9d">#00001d9d</color>
+ <color name="i_am_color_1d9e">#00001d9e</color>
+ <color name="i_am_color_1d9f">#00001d9f</color>
+ <color name="i_am_color_1da0">#00001da0</color>
+ <color name="i_am_color_1da1">#00001da1</color>
+ <color name="i_am_color_1da2">#00001da2</color>
+ <color name="i_am_color_1da3">#00001da3</color>
+ <color name="i_am_color_1da4">#00001da4</color>
+ <color name="i_am_color_1da5">#00001da5</color>
+ <color name="i_am_color_1da6">#00001da6</color>
+ <color name="i_am_color_1da7">#00001da7</color>
+ <color name="i_am_color_1da8">#00001da8</color>
+ <color name="i_am_color_1da9">#00001da9</color>
+ <color name="i_am_color_1daa">#00001daa</color>
+ <color name="i_am_color_1dab">#00001dab</color>
+ <color name="i_am_color_1dac">#00001dac</color>
+ <color name="i_am_color_1dad">#00001dad</color>
+ <color name="i_am_color_1dae">#00001dae</color>
+ <color name="i_am_color_1daf">#00001daf</color>
+ <color name="i_am_color_1db0">#00001db0</color>
+ <color name="i_am_color_1db1">#00001db1</color>
+ <color name="i_am_color_1db2">#00001db2</color>
+ <color name="i_am_color_1db3">#00001db3</color>
+ <color name="i_am_color_1db4">#00001db4</color>
+ <color name="i_am_color_1db5">#00001db5</color>
+ <color name="i_am_color_1db6">#00001db6</color>
+ <color name="i_am_color_1db7">#00001db7</color>
+ <color name="i_am_color_1db8">#00001db8</color>
+ <color name="i_am_color_1db9">#00001db9</color>
+ <color name="i_am_color_1dba">#00001dba</color>
+ <color name="i_am_color_1dbb">#00001dbb</color>
+ <color name="i_am_color_1dbc">#00001dbc</color>
+ <color name="i_am_color_1dbd">#00001dbd</color>
+ <color name="i_am_color_1dbe">#00001dbe</color>
+ <color name="i_am_color_1dbf">#00001dbf</color>
+ <color name="i_am_color_1dc0">#00001dc0</color>
+ <color name="i_am_color_1dc1">#00001dc1</color>
+ <color name="i_am_color_1dc2">#00001dc2</color>
+ <color name="i_am_color_1dc3">#00001dc3</color>
+ <color name="i_am_color_1dc4">#00001dc4</color>
+ <color name="i_am_color_1dc5">#00001dc5</color>
+ <color name="i_am_color_1dc6">#00001dc6</color>
+ <color name="i_am_color_1dc7">#00001dc7</color>
+ <color name="i_am_color_1dc8">#00001dc8</color>
+ <color name="i_am_color_1dc9">#00001dc9</color>
+ <color name="i_am_color_1dca">#00001dca</color>
+ <color name="i_am_color_1dcb">#00001dcb</color>
+ <color name="i_am_color_1dcc">#00001dcc</color>
+ <color name="i_am_color_1dcd">#00001dcd</color>
+ <color name="i_am_color_1dce">#00001dce</color>
+ <color name="i_am_color_1dcf">#00001dcf</color>
+ <color name="i_am_color_1dd0">#00001dd0</color>
+ <color name="i_am_color_1dd1">#00001dd1</color>
+ <color name="i_am_color_1dd2">#00001dd2</color>
+ <color name="i_am_color_1dd3">#00001dd3</color>
+ <color name="i_am_color_1dd4">#00001dd4</color>
+ <color name="i_am_color_1dd5">#00001dd5</color>
+ <color name="i_am_color_1dd6">#00001dd6</color>
+ <color name="i_am_color_1dd7">#00001dd7</color>
+ <color name="i_am_color_1dd8">#00001dd8</color>
+ <color name="i_am_color_1dd9">#00001dd9</color>
+ <color name="i_am_color_1dda">#00001dda</color>
+ <color name="i_am_color_1ddb">#00001ddb</color>
+ <color name="i_am_color_1ddc">#00001ddc</color>
+ <color name="i_am_color_1ddd">#00001ddd</color>
+ <color name="i_am_color_1dde">#00001dde</color>
+ <color name="i_am_color_1ddf">#00001ddf</color>
+ <color name="i_am_color_1de0">#00001de0</color>
+ <color name="i_am_color_1de1">#00001de1</color>
+ <color name="i_am_color_1de2">#00001de2</color>
+ <color name="i_am_color_1de3">#00001de3</color>
+ <color name="i_am_color_1de4">#00001de4</color>
+ <color name="i_am_color_1de5">#00001de5</color>
+ <color name="i_am_color_1de6">#00001de6</color>
+ <color name="i_am_color_1de7">#00001de7</color>
+ <color name="i_am_color_1de8">#00001de8</color>
+ <color name="i_am_color_1de9">#00001de9</color>
+ <color name="i_am_color_1dea">#00001dea</color>
+ <color name="i_am_color_1deb">#00001deb</color>
+ <color name="i_am_color_1dec">#00001dec</color>
+ <color name="i_am_color_1ded">#00001ded</color>
+ <color name="i_am_color_1dee">#00001dee</color>
+ <color name="i_am_color_1def">#00001def</color>
+ <color name="i_am_color_1df0">#00001df0</color>
+ <color name="i_am_color_1df1">#00001df1</color>
+ <color name="i_am_color_1df2">#00001df2</color>
+ <color name="i_am_color_1df3">#00001df3</color>
+ <color name="i_am_color_1df4">#00001df4</color>
+ <color name="i_am_color_1df5">#00001df5</color>
+ <color name="i_am_color_1df6">#00001df6</color>
+ <color name="i_am_color_1df7">#00001df7</color>
+ <color name="i_am_color_1df8">#00001df8</color>
+ <color name="i_am_color_1df9">#00001df9</color>
+ <color name="i_am_color_1dfa">#00001dfa</color>
+ <color name="i_am_color_1dfb">#00001dfb</color>
+ <color name="i_am_color_1dfc">#00001dfc</color>
+ <color name="i_am_color_1dfd">#00001dfd</color>
+ <color name="i_am_color_1dfe">#00001dfe</color>
+ <color name="i_am_color_1dff">#00001dff</color>
+ <color name="i_am_color_1e00">#00001e00</color>
+ <color name="i_am_color_1e01">#00001e01</color>
+ <color name="i_am_color_1e02">#00001e02</color>
+ <color name="i_am_color_1e03">#00001e03</color>
+ <color name="i_am_color_1e04">#00001e04</color>
+ <color name="i_am_color_1e05">#00001e05</color>
+ <color name="i_am_color_1e06">#00001e06</color>
+ <color name="i_am_color_1e07">#00001e07</color>
+ <color name="i_am_color_1e08">#00001e08</color>
+ <color name="i_am_color_1e09">#00001e09</color>
+ <color name="i_am_color_1e0a">#00001e0a</color>
+ <color name="i_am_color_1e0b">#00001e0b</color>
+ <color name="i_am_color_1e0c">#00001e0c</color>
+ <color name="i_am_color_1e0d">#00001e0d</color>
+ <color name="i_am_color_1e0e">#00001e0e</color>
+ <color name="i_am_color_1e0f">#00001e0f</color>
+ <color name="i_am_color_1e10">#00001e10</color>
+ <color name="i_am_color_1e11">#00001e11</color>
+ <color name="i_am_color_1e12">#00001e12</color>
+ <color name="i_am_color_1e13">#00001e13</color>
+ <color name="i_am_color_1e14">#00001e14</color>
+ <color name="i_am_color_1e15">#00001e15</color>
+ <color name="i_am_color_1e16">#00001e16</color>
+ <color name="i_am_color_1e17">#00001e17</color>
+ <color name="i_am_color_1e18">#00001e18</color>
+ <color name="i_am_color_1e19">#00001e19</color>
+ <color name="i_am_color_1e1a">#00001e1a</color>
+ <color name="i_am_color_1e1b">#00001e1b</color>
+ <color name="i_am_color_1e1c">#00001e1c</color>
+ <color name="i_am_color_1e1d">#00001e1d</color>
+ <color name="i_am_color_1e1e">#00001e1e</color>
+ <color name="i_am_color_1e1f">#00001e1f</color>
+ <color name="i_am_color_1e20">#00001e20</color>
+ <color name="i_am_color_1e21">#00001e21</color>
+ <color name="i_am_color_1e22">#00001e22</color>
+ <color name="i_am_color_1e23">#00001e23</color>
+ <color name="i_am_color_1e24">#00001e24</color>
+ <color name="i_am_color_1e25">#00001e25</color>
+ <color name="i_am_color_1e26">#00001e26</color>
+ <color name="i_am_color_1e27">#00001e27</color>
+ <color name="i_am_color_1e28">#00001e28</color>
+ <color name="i_am_color_1e29">#00001e29</color>
+ <color name="i_am_color_1e2a">#00001e2a</color>
+ <color name="i_am_color_1e2b">#00001e2b</color>
+ <color name="i_am_color_1e2c">#00001e2c</color>
+ <color name="i_am_color_1e2d">#00001e2d</color>
+ <color name="i_am_color_1e2e">#00001e2e</color>
+ <color name="i_am_color_1e2f">#00001e2f</color>
+ <color name="i_am_color_1e30">#00001e30</color>
+ <color name="i_am_color_1e31">#00001e31</color>
+ <color name="i_am_color_1e32">#00001e32</color>
+ <color name="i_am_color_1e33">#00001e33</color>
+ <color name="i_am_color_1e34">#00001e34</color>
+ <color name="i_am_color_1e35">#00001e35</color>
+ <color name="i_am_color_1e36">#00001e36</color>
+ <color name="i_am_color_1e37">#00001e37</color>
+ <color name="i_am_color_1e38">#00001e38</color>
+ <color name="i_am_color_1e39">#00001e39</color>
+ <color name="i_am_color_1e3a">#00001e3a</color>
+ <color name="i_am_color_1e3b">#00001e3b</color>
+ <color name="i_am_color_1e3c">#00001e3c</color>
+ <color name="i_am_color_1e3d">#00001e3d</color>
+ <color name="i_am_color_1e3e">#00001e3e</color>
+ <color name="i_am_color_1e3f">#00001e3f</color>
+ <color name="i_am_color_1e40">#00001e40</color>
+ <color name="i_am_color_1e41">#00001e41</color>
+ <color name="i_am_color_1e42">#00001e42</color>
+ <color name="i_am_color_1e43">#00001e43</color>
+ <color name="i_am_color_1e44">#00001e44</color>
+ <color name="i_am_color_1e45">#00001e45</color>
+ <color name="i_am_color_1e46">#00001e46</color>
+ <color name="i_am_color_1e47">#00001e47</color>
+ <color name="i_am_color_1e48">#00001e48</color>
+ <color name="i_am_color_1e49">#00001e49</color>
+ <color name="i_am_color_1e4a">#00001e4a</color>
+ <color name="i_am_color_1e4b">#00001e4b</color>
+ <color name="i_am_color_1e4c">#00001e4c</color>
+ <color name="i_am_color_1e4d">#00001e4d</color>
+ <color name="i_am_color_1e4e">#00001e4e</color>
+ <color name="i_am_color_1e4f">#00001e4f</color>
+ <color name="i_am_color_1e50">#00001e50</color>
+ <color name="i_am_color_1e51">#00001e51</color>
+ <color name="i_am_color_1e52">#00001e52</color>
+ <color name="i_am_color_1e53">#00001e53</color>
+ <color name="i_am_color_1e54">#00001e54</color>
+ <color name="i_am_color_1e55">#00001e55</color>
+ <color name="i_am_color_1e56">#00001e56</color>
+ <color name="i_am_color_1e57">#00001e57</color>
+ <color name="i_am_color_1e58">#00001e58</color>
+ <color name="i_am_color_1e59">#00001e59</color>
+ <color name="i_am_color_1e5a">#00001e5a</color>
+ <color name="i_am_color_1e5b">#00001e5b</color>
+ <color name="i_am_color_1e5c">#00001e5c</color>
+ <color name="i_am_color_1e5d">#00001e5d</color>
+ <color name="i_am_color_1e5e">#00001e5e</color>
+ <color name="i_am_color_1e5f">#00001e5f</color>
+ <color name="i_am_color_1e60">#00001e60</color>
+ <color name="i_am_color_1e61">#00001e61</color>
+ <color name="i_am_color_1e62">#00001e62</color>
+ <color name="i_am_color_1e63">#00001e63</color>
+ <color name="i_am_color_1e64">#00001e64</color>
+ <color name="i_am_color_1e65">#00001e65</color>
+ <color name="i_am_color_1e66">#00001e66</color>
+ <color name="i_am_color_1e67">#00001e67</color>
+ <color name="i_am_color_1e68">#00001e68</color>
+ <color name="i_am_color_1e69">#00001e69</color>
+ <color name="i_am_color_1e6a">#00001e6a</color>
+ <color name="i_am_color_1e6b">#00001e6b</color>
+ <color name="i_am_color_1e6c">#00001e6c</color>
+ <color name="i_am_color_1e6d">#00001e6d</color>
+ <color name="i_am_color_1e6e">#00001e6e</color>
+ <color name="i_am_color_1e6f">#00001e6f</color>
+ <color name="i_am_color_1e70">#00001e70</color>
+ <color name="i_am_color_1e71">#00001e71</color>
+ <color name="i_am_color_1e72">#00001e72</color>
+ <color name="i_am_color_1e73">#00001e73</color>
+ <color name="i_am_color_1e74">#00001e74</color>
+ <color name="i_am_color_1e75">#00001e75</color>
+ <color name="i_am_color_1e76">#00001e76</color>
+ <color name="i_am_color_1e77">#00001e77</color>
+ <color name="i_am_color_1e78">#00001e78</color>
+ <color name="i_am_color_1e79">#00001e79</color>
+ <color name="i_am_color_1e7a">#00001e7a</color>
+ <color name="i_am_color_1e7b">#00001e7b</color>
+ <color name="i_am_color_1e7c">#00001e7c</color>
+ <color name="i_am_color_1e7d">#00001e7d</color>
+ <color name="i_am_color_1e7e">#00001e7e</color>
+ <color name="i_am_color_1e7f">#00001e7f</color>
+ <color name="i_am_color_1e80">#00001e80</color>
+ <color name="i_am_color_1e81">#00001e81</color>
+ <color name="i_am_color_1e82">#00001e82</color>
+ <color name="i_am_color_1e83">#00001e83</color>
+ <color name="i_am_color_1e84">#00001e84</color>
+ <color name="i_am_color_1e85">#00001e85</color>
+ <color name="i_am_color_1e86">#00001e86</color>
+ <color name="i_am_color_1e87">#00001e87</color>
+ <color name="i_am_color_1e88">#00001e88</color>
+ <color name="i_am_color_1e89">#00001e89</color>
+ <color name="i_am_color_1e8a">#00001e8a</color>
+ <color name="i_am_color_1e8b">#00001e8b</color>
+ <color name="i_am_color_1e8c">#00001e8c</color>
+ <color name="i_am_color_1e8d">#00001e8d</color>
+ <color name="i_am_color_1e8e">#00001e8e</color>
+ <color name="i_am_color_1e8f">#00001e8f</color>
+ <color name="i_am_color_1e90">#00001e90</color>
+ <color name="i_am_color_1e91">#00001e91</color>
+ <color name="i_am_color_1e92">#00001e92</color>
+ <color name="i_am_color_1e93">#00001e93</color>
+ <color name="i_am_color_1e94">#00001e94</color>
+ <color name="i_am_color_1e95">#00001e95</color>
+ <color name="i_am_color_1e96">#00001e96</color>
+ <color name="i_am_color_1e97">#00001e97</color>
+ <color name="i_am_color_1e98">#00001e98</color>
+ <color name="i_am_color_1e99">#00001e99</color>
+ <color name="i_am_color_1e9a">#00001e9a</color>
+ <color name="i_am_color_1e9b">#00001e9b</color>
+ <color name="i_am_color_1e9c">#00001e9c</color>
+ <color name="i_am_color_1e9d">#00001e9d</color>
+ <color name="i_am_color_1e9e">#00001e9e</color>
+ <color name="i_am_color_1e9f">#00001e9f</color>
+ <color name="i_am_color_1ea0">#00001ea0</color>
+ <color name="i_am_color_1ea1">#00001ea1</color>
+ <color name="i_am_color_1ea2">#00001ea2</color>
+ <color name="i_am_color_1ea3">#00001ea3</color>
+ <color name="i_am_color_1ea4">#00001ea4</color>
+ <color name="i_am_color_1ea5">#00001ea5</color>
+ <color name="i_am_color_1ea6">#00001ea6</color>
+ <color name="i_am_color_1ea7">#00001ea7</color>
+ <color name="i_am_color_1ea8">#00001ea8</color>
+ <color name="i_am_color_1ea9">#00001ea9</color>
+ <color name="i_am_color_1eaa">#00001eaa</color>
+ <color name="i_am_color_1eab">#00001eab</color>
+ <color name="i_am_color_1eac">#00001eac</color>
+ <color name="i_am_color_1ead">#00001ead</color>
+ <color name="i_am_color_1eae">#00001eae</color>
+ <color name="i_am_color_1eaf">#00001eaf</color>
+ <color name="i_am_color_1eb0">#00001eb0</color>
+ <color name="i_am_color_1eb1">#00001eb1</color>
+ <color name="i_am_color_1eb2">#00001eb2</color>
+ <color name="i_am_color_1eb3">#00001eb3</color>
+ <color name="i_am_color_1eb4">#00001eb4</color>
+ <color name="i_am_color_1eb5">#00001eb5</color>
+ <color name="i_am_color_1eb6">#00001eb6</color>
+ <color name="i_am_color_1eb7">#00001eb7</color>
+ <color name="i_am_color_1eb8">#00001eb8</color>
+ <color name="i_am_color_1eb9">#00001eb9</color>
+ <color name="i_am_color_1eba">#00001eba</color>
+ <color name="i_am_color_1ebb">#00001ebb</color>
+ <color name="i_am_color_1ebc">#00001ebc</color>
+ <color name="i_am_color_1ebd">#00001ebd</color>
+ <color name="i_am_color_1ebe">#00001ebe</color>
+ <color name="i_am_color_1ebf">#00001ebf</color>
+ <color name="i_am_color_1ec0">#00001ec0</color>
+ <color name="i_am_color_1ec1">#00001ec1</color>
+ <color name="i_am_color_1ec2">#00001ec2</color>
+ <color name="i_am_color_1ec3">#00001ec3</color>
+ <color name="i_am_color_1ec4">#00001ec4</color>
+ <color name="i_am_color_1ec5">#00001ec5</color>
+ <color name="i_am_color_1ec6">#00001ec6</color>
+ <color name="i_am_color_1ec7">#00001ec7</color>
+ <color name="i_am_color_1ec8">#00001ec8</color>
+ <color name="i_am_color_1ec9">#00001ec9</color>
+ <color name="i_am_color_1eca">#00001eca</color>
+ <color name="i_am_color_1ecb">#00001ecb</color>
+ <color name="i_am_color_1ecc">#00001ecc</color>
+ <color name="i_am_color_1ecd">#00001ecd</color>
+ <color name="i_am_color_1ece">#00001ece</color>
+ <color name="i_am_color_1ecf">#00001ecf</color>
+ <color name="i_am_color_1ed0">#00001ed0</color>
+ <color name="i_am_color_1ed1">#00001ed1</color>
+ <color name="i_am_color_1ed2">#00001ed2</color>
+ <color name="i_am_color_1ed3">#00001ed3</color>
+ <color name="i_am_color_1ed4">#00001ed4</color>
+ <color name="i_am_color_1ed5">#00001ed5</color>
+ <color name="i_am_color_1ed6">#00001ed6</color>
+ <color name="i_am_color_1ed7">#00001ed7</color>
+ <color name="i_am_color_1ed8">#00001ed8</color>
+ <color name="i_am_color_1ed9">#00001ed9</color>
+ <color name="i_am_color_1eda">#00001eda</color>
+ <color name="i_am_color_1edb">#00001edb</color>
+ <color name="i_am_color_1edc">#00001edc</color>
+ <color name="i_am_color_1edd">#00001edd</color>
+ <color name="i_am_color_1ede">#00001ede</color>
+ <color name="i_am_color_1edf">#00001edf</color>
+ <color name="i_am_color_1ee0">#00001ee0</color>
+ <color name="i_am_color_1ee1">#00001ee1</color>
+ <color name="i_am_color_1ee2">#00001ee2</color>
+ <color name="i_am_color_1ee3">#00001ee3</color>
+ <color name="i_am_color_1ee4">#00001ee4</color>
+ <color name="i_am_color_1ee5">#00001ee5</color>
+ <color name="i_am_color_1ee6">#00001ee6</color>
+ <color name="i_am_color_1ee7">#00001ee7</color>
+ <color name="i_am_color_1ee8">#00001ee8</color>
+ <color name="i_am_color_1ee9">#00001ee9</color>
+ <color name="i_am_color_1eea">#00001eea</color>
+ <color name="i_am_color_1eeb">#00001eeb</color>
+ <color name="i_am_color_1eec">#00001eec</color>
+ <color name="i_am_color_1eed">#00001eed</color>
+ <color name="i_am_color_1eee">#00001eee</color>
+ <color name="i_am_color_1eef">#00001eef</color>
+ <color name="i_am_color_1ef0">#00001ef0</color>
+ <color name="i_am_color_1ef1">#00001ef1</color>
+ <color name="i_am_color_1ef2">#00001ef2</color>
+ <color name="i_am_color_1ef3">#00001ef3</color>
+ <color name="i_am_color_1ef4">#00001ef4</color>
+ <color name="i_am_color_1ef5">#00001ef5</color>
+ <color name="i_am_color_1ef6">#00001ef6</color>
+ <color name="i_am_color_1ef7">#00001ef7</color>
+ <color name="i_am_color_1ef8">#00001ef8</color>
+ <color name="i_am_color_1ef9">#00001ef9</color>
+ <color name="i_am_color_1efa">#00001efa</color>
+ <color name="i_am_color_1efb">#00001efb</color>
+ <color name="i_am_color_1efc">#00001efc</color>
+ <color name="i_am_color_1efd">#00001efd</color>
+ <color name="i_am_color_1efe">#00001efe</color>
+ <color name="i_am_color_1eff">#00001eff</color>
+ <color name="i_am_color_1f00">#00001f00</color>
+ <color name="i_am_color_1f01">#00001f01</color>
+ <color name="i_am_color_1f02">#00001f02</color>
+ <color name="i_am_color_1f03">#00001f03</color>
+ <color name="i_am_color_1f04">#00001f04</color>
+ <color name="i_am_color_1f05">#00001f05</color>
+ <color name="i_am_color_1f06">#00001f06</color>
+ <color name="i_am_color_1f07">#00001f07</color>
+ <color name="i_am_color_1f08">#00001f08</color>
+ <color name="i_am_color_1f09">#00001f09</color>
+ <color name="i_am_color_1f0a">#00001f0a</color>
+ <color name="i_am_color_1f0b">#00001f0b</color>
+ <color name="i_am_color_1f0c">#00001f0c</color>
+ <color name="i_am_color_1f0d">#00001f0d</color>
+ <color name="i_am_color_1f0e">#00001f0e</color>
+ <color name="i_am_color_1f0f">#00001f0f</color>
+ <color name="i_am_color_1f10">#00001f10</color>
+ <color name="i_am_color_1f11">#00001f11</color>
+ <color name="i_am_color_1f12">#00001f12</color>
+ <color name="i_am_color_1f13">#00001f13</color>
+ <color name="i_am_color_1f14">#00001f14</color>
+ <color name="i_am_color_1f15">#00001f15</color>
+ <color name="i_am_color_1f16">#00001f16</color>
+ <color name="i_am_color_1f17">#00001f17</color>
+ <color name="i_am_color_1f18">#00001f18</color>
+ <color name="i_am_color_1f19">#00001f19</color>
+ <color name="i_am_color_1f1a">#00001f1a</color>
+ <color name="i_am_color_1f1b">#00001f1b</color>
+ <color name="i_am_color_1f1c">#00001f1c</color>
+ <color name="i_am_color_1f1d">#00001f1d</color>
+ <color name="i_am_color_1f1e">#00001f1e</color>
+ <color name="i_am_color_1f1f">#00001f1f</color>
+ <color name="i_am_color_1f20">#00001f20</color>
+ <color name="i_am_color_1f21">#00001f21</color>
+ <color name="i_am_color_1f22">#00001f22</color>
+ <color name="i_am_color_1f23">#00001f23</color>
+ <color name="i_am_color_1f24">#00001f24</color>
+ <color name="i_am_color_1f25">#00001f25</color>
+ <color name="i_am_color_1f26">#00001f26</color>
+ <color name="i_am_color_1f27">#00001f27</color>
+ <color name="i_am_color_1f28">#00001f28</color>
+ <color name="i_am_color_1f29">#00001f29</color>
+ <color name="i_am_color_1f2a">#00001f2a</color>
+ <color name="i_am_color_1f2b">#00001f2b</color>
+ <color name="i_am_color_1f2c">#00001f2c</color>
+ <color name="i_am_color_1f2d">#00001f2d</color>
+ <color name="i_am_color_1f2e">#00001f2e</color>
+ <color name="i_am_color_1f2f">#00001f2f</color>
+ <color name="i_am_color_1f30">#00001f30</color>
+ <color name="i_am_color_1f31">#00001f31</color>
+ <color name="i_am_color_1f32">#00001f32</color>
+ <color name="i_am_color_1f33">#00001f33</color>
+ <color name="i_am_color_1f34">#00001f34</color>
+ <color name="i_am_color_1f35">#00001f35</color>
+ <color name="i_am_color_1f36">#00001f36</color>
+ <color name="i_am_color_1f37">#00001f37</color>
+ <color name="i_am_color_1f38">#00001f38</color>
+ <color name="i_am_color_1f39">#00001f39</color>
+ <color name="i_am_color_1f3a">#00001f3a</color>
+ <color name="i_am_color_1f3b">#00001f3b</color>
+ <color name="i_am_color_1f3c">#00001f3c</color>
+ <color name="i_am_color_1f3d">#00001f3d</color>
+ <color name="i_am_color_1f3e">#00001f3e</color>
+ <color name="i_am_color_1f3f">#00001f3f</color>
+ <color name="i_am_color_1f40">#00001f40</color>
+ <color name="i_am_color_1f41">#00001f41</color>
+ <color name="i_am_color_1f42">#00001f42</color>
+ <color name="i_am_color_1f43">#00001f43</color>
+ <color name="i_am_color_1f44">#00001f44</color>
+ <color name="i_am_color_1f45">#00001f45</color>
+ <color name="i_am_color_1f46">#00001f46</color>
+ <color name="i_am_color_1f47">#00001f47</color>
+ <color name="i_am_color_1f48">#00001f48</color>
+ <color name="i_am_color_1f49">#00001f49</color>
+ <color name="i_am_color_1f4a">#00001f4a</color>
+ <color name="i_am_color_1f4b">#00001f4b</color>
+ <color name="i_am_color_1f4c">#00001f4c</color>
+ <color name="i_am_color_1f4d">#00001f4d</color>
+ <color name="i_am_color_1f4e">#00001f4e</color>
+ <color name="i_am_color_1f4f">#00001f4f</color>
+ <color name="i_am_color_1f50">#00001f50</color>
+ <color name="i_am_color_1f51">#00001f51</color>
+ <color name="i_am_color_1f52">#00001f52</color>
+ <color name="i_am_color_1f53">#00001f53</color>
+ <color name="i_am_color_1f54">#00001f54</color>
+ <color name="i_am_color_1f55">#00001f55</color>
+ <color name="i_am_color_1f56">#00001f56</color>
+ <color name="i_am_color_1f57">#00001f57</color>
+ <color name="i_am_color_1f58">#00001f58</color>
+ <color name="i_am_color_1f59">#00001f59</color>
+ <color name="i_am_color_1f5a">#00001f5a</color>
+ <color name="i_am_color_1f5b">#00001f5b</color>
+ <color name="i_am_color_1f5c">#00001f5c</color>
+ <color name="i_am_color_1f5d">#00001f5d</color>
+ <color name="i_am_color_1f5e">#00001f5e</color>
+ <color name="i_am_color_1f5f">#00001f5f</color>
+ <color name="i_am_color_1f60">#00001f60</color>
+ <color name="i_am_color_1f61">#00001f61</color>
+ <color name="i_am_color_1f62">#00001f62</color>
+ <color name="i_am_color_1f63">#00001f63</color>
+ <color name="i_am_color_1f64">#00001f64</color>
+ <color name="i_am_color_1f65">#00001f65</color>
+ <color name="i_am_color_1f66">#00001f66</color>
+ <color name="i_am_color_1f67">#00001f67</color>
+ <color name="i_am_color_1f68">#00001f68</color>
+ <color name="i_am_color_1f69">#00001f69</color>
+ <color name="i_am_color_1f6a">#00001f6a</color>
+ <color name="i_am_color_1f6b">#00001f6b</color>
+ <color name="i_am_color_1f6c">#00001f6c</color>
+ <color name="i_am_color_1f6d">#00001f6d</color>
+ <color name="i_am_color_1f6e">#00001f6e</color>
+ <color name="i_am_color_1f6f">#00001f6f</color>
+ <color name="i_am_color_1f70">#00001f70</color>
+ <color name="i_am_color_1f71">#00001f71</color>
+ <color name="i_am_color_1f72">#00001f72</color>
+ <color name="i_am_color_1f73">#00001f73</color>
+ <color name="i_am_color_1f74">#00001f74</color>
+ <color name="i_am_color_1f75">#00001f75</color>
+ <color name="i_am_color_1f76">#00001f76</color>
+ <color name="i_am_color_1f77">#00001f77</color>
+ <color name="i_am_color_1f78">#00001f78</color>
+ <color name="i_am_color_1f79">#00001f79</color>
+ <color name="i_am_color_1f7a">#00001f7a</color>
+ <color name="i_am_color_1f7b">#00001f7b</color>
+ <color name="i_am_color_1f7c">#00001f7c</color>
+ <color name="i_am_color_1f7d">#00001f7d</color>
+ <color name="i_am_color_1f7e">#00001f7e</color>
+ <color name="i_am_color_1f7f">#00001f7f</color>
+ <color name="i_am_color_1f80">#00001f80</color>
+ <color name="i_am_color_1f81">#00001f81</color>
+ <color name="i_am_color_1f82">#00001f82</color>
+ <color name="i_am_color_1f83">#00001f83</color>
+ <color name="i_am_color_1f84">#00001f84</color>
+ <color name="i_am_color_1f85">#00001f85</color>
+ <color name="i_am_color_1f86">#00001f86</color>
+ <color name="i_am_color_1f87">#00001f87</color>
+ <color name="i_am_color_1f88">#00001f88</color>
+ <color name="i_am_color_1f89">#00001f89</color>
+ <color name="i_am_color_1f8a">#00001f8a</color>
+ <color name="i_am_color_1f8b">#00001f8b</color>
+ <color name="i_am_color_1f8c">#00001f8c</color>
+ <color name="i_am_color_1f8d">#00001f8d</color>
+ <color name="i_am_color_1f8e">#00001f8e</color>
+ <color name="i_am_color_1f8f">#00001f8f</color>
+ <color name="i_am_color_1f90">#00001f90</color>
+ <color name="i_am_color_1f91">#00001f91</color>
+ <color name="i_am_color_1f92">#00001f92</color>
+ <color name="i_am_color_1f93">#00001f93</color>
+ <color name="i_am_color_1f94">#00001f94</color>
+ <color name="i_am_color_1f95">#00001f95</color>
+ <color name="i_am_color_1f96">#00001f96</color>
+ <color name="i_am_color_1f97">#00001f97</color>
+ <color name="i_am_color_1f98">#00001f98</color>
+ <color name="i_am_color_1f99">#00001f99</color>
+ <color name="i_am_color_1f9a">#00001f9a</color>
+ <color name="i_am_color_1f9b">#00001f9b</color>
+ <color name="i_am_color_1f9c">#00001f9c</color>
+ <color name="i_am_color_1f9d">#00001f9d</color>
+ <color name="i_am_color_1f9e">#00001f9e</color>
+ <color name="i_am_color_1f9f">#00001f9f</color>
+ <color name="i_am_color_1fa0">#00001fa0</color>
+ <color name="i_am_color_1fa1">#00001fa1</color>
+ <color name="i_am_color_1fa2">#00001fa2</color>
+ <color name="i_am_color_1fa3">#00001fa3</color>
+ <color name="i_am_color_1fa4">#00001fa4</color>
+ <color name="i_am_color_1fa5">#00001fa5</color>
+ <color name="i_am_color_1fa6">#00001fa6</color>
+ <color name="i_am_color_1fa7">#00001fa7</color>
+ <color name="i_am_color_1fa8">#00001fa8</color>
+ <color name="i_am_color_1fa9">#00001fa9</color>
+ <color name="i_am_color_1faa">#00001faa</color>
+ <color name="i_am_color_1fab">#00001fab</color>
+ <color name="i_am_color_1fac">#00001fac</color>
+ <color name="i_am_color_1fad">#00001fad</color>
+ <color name="i_am_color_1fae">#00001fae</color>
+ <color name="i_am_color_1faf">#00001faf</color>
+ <color name="i_am_color_1fb0">#00001fb0</color>
+ <color name="i_am_color_1fb1">#00001fb1</color>
+ <color name="i_am_color_1fb2">#00001fb2</color>
+ <color name="i_am_color_1fb3">#00001fb3</color>
+ <color name="i_am_color_1fb4">#00001fb4</color>
+ <color name="i_am_color_1fb5">#00001fb5</color>
+ <color name="i_am_color_1fb6">#00001fb6</color>
+ <color name="i_am_color_1fb7">#00001fb7</color>
+ <color name="i_am_color_1fb8">#00001fb8</color>
+ <color name="i_am_color_1fb9">#00001fb9</color>
+ <color name="i_am_color_1fba">#00001fba</color>
+ <color name="i_am_color_1fbb">#00001fbb</color>
+ <color name="i_am_color_1fbc">#00001fbc</color>
+ <color name="i_am_color_1fbd">#00001fbd</color>
+ <color name="i_am_color_1fbe">#00001fbe</color>
+ <color name="i_am_color_1fbf">#00001fbf</color>
+ <color name="i_am_color_1fc0">#00001fc0</color>
+ <color name="i_am_color_1fc1">#00001fc1</color>
+ <color name="i_am_color_1fc2">#00001fc2</color>
+ <color name="i_am_color_1fc3">#00001fc3</color>
+ <color name="i_am_color_1fc4">#00001fc4</color>
+ <color name="i_am_color_1fc5">#00001fc5</color>
+ <color name="i_am_color_1fc6">#00001fc6</color>
+ <color name="i_am_color_1fc7">#00001fc7</color>
+ <color name="i_am_color_1fc8">#00001fc8</color>
+ <color name="i_am_color_1fc9">#00001fc9</color>
+ <color name="i_am_color_1fca">#00001fca</color>
+ <color name="i_am_color_1fcb">#00001fcb</color>
+ <color name="i_am_color_1fcc">#00001fcc</color>
+ <color name="i_am_color_1fcd">#00001fcd</color>
+ <color name="i_am_color_1fce">#00001fce</color>
+ <color name="i_am_color_1fcf">#00001fcf</color>
+ <color name="i_am_color_1fd0">#00001fd0</color>
+ <color name="i_am_color_1fd1">#00001fd1</color>
+ <color name="i_am_color_1fd2">#00001fd2</color>
+ <color name="i_am_color_1fd3">#00001fd3</color>
+ <color name="i_am_color_1fd4">#00001fd4</color>
+ <color name="i_am_color_1fd5">#00001fd5</color>
+ <color name="i_am_color_1fd6">#00001fd6</color>
+ <color name="i_am_color_1fd7">#00001fd7</color>
+ <color name="i_am_color_1fd8">#00001fd8</color>
+ <color name="i_am_color_1fd9">#00001fd9</color>
+ <color name="i_am_color_1fda">#00001fda</color>
+ <color name="i_am_color_1fdb">#00001fdb</color>
+ <color name="i_am_color_1fdc">#00001fdc</color>
+ <color name="i_am_color_1fdd">#00001fdd</color>
+ <color name="i_am_color_1fde">#00001fde</color>
+ <color name="i_am_color_1fdf">#00001fdf</color>
+ <color name="i_am_color_1fe0">#00001fe0</color>
+ <color name="i_am_color_1fe1">#00001fe1</color>
+ <color name="i_am_color_1fe2">#00001fe2</color>
+ <color name="i_am_color_1fe3">#00001fe3</color>
+ <color name="i_am_color_1fe4">#00001fe4</color>
+ <color name="i_am_color_1fe5">#00001fe5</color>
+ <color name="i_am_color_1fe6">#00001fe6</color>
+ <color name="i_am_color_1fe7">#00001fe7</color>
+ <color name="i_am_color_1fe8">#00001fe8</color>
+ <color name="i_am_color_1fe9">#00001fe9</color>
+ <color name="i_am_color_1fea">#00001fea</color>
+ <color name="i_am_color_1feb">#00001feb</color>
+ <color name="i_am_color_1fec">#00001fec</color>
+ <color name="i_am_color_1fed">#00001fed</color>
+ <color name="i_am_color_1fee">#00001fee</color>
+ <color name="i_am_color_1fef">#00001fef</color>
+ <color name="i_am_color_1ff0">#00001ff0</color>
+ <color name="i_am_color_1ff1">#00001ff1</color>
+ <color name="i_am_color_1ff2">#00001ff2</color>
+ <color name="i_am_color_1ff3">#00001ff3</color>
+ <color name="i_am_color_1ff4">#00001ff4</color>
+ <color name="i_am_color_1ff5">#00001ff5</color>
+ <color name="i_am_color_1ff6">#00001ff6</color>
+ <color name="i_am_color_1ff7">#00001ff7</color>
+ <color name="i_am_color_1ff8">#00001ff8</color>
+ <color name="i_am_color_1ff9">#00001ff9</color>
+ <color name="i_am_color_1ffa">#00001ffa</color>
+ <color name="i_am_color_1ffb">#00001ffb</color>
+ <color name="i_am_color_1ffc">#00001ffc</color>
+ <color name="i_am_color_1ffd">#00001ffd</color>
+ <color name="i_am_color_1ffe">#00001ffe</color>
+ <color name="i_am_color_1fff">#00001fff</color>
+ <color name="i_am_color_2000">#00002000</color>
+ <color name="i_am_color_2001">#00002001</color>
+ <color name="i_am_color_2002">#00002002</color>
+ <color name="i_am_color_2003">#00002003</color>
+ <color name="i_am_color_2004">#00002004</color>
+ <color name="i_am_color_2005">#00002005</color>
+ <color name="i_am_color_2006">#00002006</color>
+ <color name="i_am_color_2007">#00002007</color>
+ <color name="i_am_color_2008">#00002008</color>
+ <color name="i_am_color_2009">#00002009</color>
+ <color name="i_am_color_200a">#0000200a</color>
+ <color name="i_am_color_200b">#0000200b</color>
+ <color name="i_am_color_200c">#0000200c</color>
+ <color name="i_am_color_200d">#0000200d</color>
+ <color name="i_am_color_200e">#0000200e</color>
+ <color name="i_am_color_200f">#0000200f</color>
+ <color name="i_am_color_2010">#00002010</color>
+ <color name="i_am_color_2011">#00002011</color>
+ <color name="i_am_color_2012">#00002012</color>
+ <color name="i_am_color_2013">#00002013</color>
+ <color name="i_am_color_2014">#00002014</color>
+ <color name="i_am_color_2015">#00002015</color>
+ <color name="i_am_color_2016">#00002016</color>
+ <color name="i_am_color_2017">#00002017</color>
+ <color name="i_am_color_2018">#00002018</color>
+ <color name="i_am_color_2019">#00002019</color>
+ <color name="i_am_color_201a">#0000201a</color>
+ <color name="i_am_color_201b">#0000201b</color>
+ <color name="i_am_color_201c">#0000201c</color>
+ <color name="i_am_color_201d">#0000201d</color>
+ <color name="i_am_color_201e">#0000201e</color>
+ <color name="i_am_color_201f">#0000201f</color>
+ <color name="i_am_color_2020">#00002020</color>
+ <color name="i_am_color_2021">#00002021</color>
+ <color name="i_am_color_2022">#00002022</color>
+ <color name="i_am_color_2023">#00002023</color>
+ <color name="i_am_color_2024">#00002024</color>
+ <color name="i_am_color_2025">#00002025</color>
+ <color name="i_am_color_2026">#00002026</color>
+ <color name="i_am_color_2027">#00002027</color>
+ <color name="i_am_color_2028">#00002028</color>
+ <color name="i_am_color_2029">#00002029</color>
+ <color name="i_am_color_202a">#0000202a</color>
+ <color name="i_am_color_202b">#0000202b</color>
+ <color name="i_am_color_202c">#0000202c</color>
+ <color name="i_am_color_202d">#0000202d</color>
+ <color name="i_am_color_202e">#0000202e</color>
+ <color name="i_am_color_202f">#0000202f</color>
+ <color name="i_am_color_2030">#00002030</color>
+ <color name="i_am_color_2031">#00002031</color>
+ <color name="i_am_color_2032">#00002032</color>
+ <color name="i_am_color_2033">#00002033</color>
+ <color name="i_am_color_2034">#00002034</color>
+ <color name="i_am_color_2035">#00002035</color>
+ <color name="i_am_color_2036">#00002036</color>
+ <color name="i_am_color_2037">#00002037</color>
+ <color name="i_am_color_2038">#00002038</color>
+ <color name="i_am_color_2039">#00002039</color>
+ <color name="i_am_color_203a">#0000203a</color>
+ <color name="i_am_color_203b">#0000203b</color>
+ <color name="i_am_color_203c">#0000203c</color>
+ <color name="i_am_color_203d">#0000203d</color>
+ <color name="i_am_color_203e">#0000203e</color>
+ <color name="i_am_color_203f">#0000203f</color>
+ <color name="i_am_color_2040">#00002040</color>
+ <color name="i_am_color_2041">#00002041</color>
+ <color name="i_am_color_2042">#00002042</color>
+ <color name="i_am_color_2043">#00002043</color>
+ <color name="i_am_color_2044">#00002044</color>
+ <color name="i_am_color_2045">#00002045</color>
+ <color name="i_am_color_2046">#00002046</color>
+ <color name="i_am_color_2047">#00002047</color>
+ <color name="i_am_color_2048">#00002048</color>
+ <color name="i_am_color_2049">#00002049</color>
+ <color name="i_am_color_204a">#0000204a</color>
+ <color name="i_am_color_204b">#0000204b</color>
+ <color name="i_am_color_204c">#0000204c</color>
+ <color name="i_am_color_204d">#0000204d</color>
+ <color name="i_am_color_204e">#0000204e</color>
+ <color name="i_am_color_204f">#0000204f</color>
+ <color name="i_am_color_2050">#00002050</color>
+ <color name="i_am_color_2051">#00002051</color>
+ <color name="i_am_color_2052">#00002052</color>
+ <color name="i_am_color_2053">#00002053</color>
+ <color name="i_am_color_2054">#00002054</color>
+ <color name="i_am_color_2055">#00002055</color>
+ <color name="i_am_color_2056">#00002056</color>
+ <color name="i_am_color_2057">#00002057</color>
+ <color name="i_am_color_2058">#00002058</color>
+ <color name="i_am_color_2059">#00002059</color>
+ <color name="i_am_color_205a">#0000205a</color>
+ <color name="i_am_color_205b">#0000205b</color>
+ <color name="i_am_color_205c">#0000205c</color>
+ <color name="i_am_color_205d">#0000205d</color>
+ <color name="i_am_color_205e">#0000205e</color>
+ <color name="i_am_color_205f">#0000205f</color>
+ <color name="i_am_color_2060">#00002060</color>
+ <color name="i_am_color_2061">#00002061</color>
+ <color name="i_am_color_2062">#00002062</color>
+ <color name="i_am_color_2063">#00002063</color>
+ <color name="i_am_color_2064">#00002064</color>
+ <color name="i_am_color_2065">#00002065</color>
+ <color name="i_am_color_2066">#00002066</color>
+ <color name="i_am_color_2067">#00002067</color>
+ <color name="i_am_color_2068">#00002068</color>
+ <color name="i_am_color_2069">#00002069</color>
+ <color name="i_am_color_206a">#0000206a</color>
+ <color name="i_am_color_206b">#0000206b</color>
+ <color name="i_am_color_206c">#0000206c</color>
+ <color name="i_am_color_206d">#0000206d</color>
+ <color name="i_am_color_206e">#0000206e</color>
+ <color name="i_am_color_206f">#0000206f</color>
+ <color name="i_am_color_2070">#00002070</color>
+ <color name="i_am_color_2071">#00002071</color>
+ <color name="i_am_color_2072">#00002072</color>
+ <color name="i_am_color_2073">#00002073</color>
+ <color name="i_am_color_2074">#00002074</color>
+ <color name="i_am_color_2075">#00002075</color>
+ <color name="i_am_color_2076">#00002076</color>
+ <color name="i_am_color_2077">#00002077</color>
+ <color name="i_am_color_2078">#00002078</color>
+ <color name="i_am_color_2079">#00002079</color>
+ <color name="i_am_color_207a">#0000207a</color>
+ <color name="i_am_color_207b">#0000207b</color>
+ <color name="i_am_color_207c">#0000207c</color>
+ <color name="i_am_color_207d">#0000207d</color>
+ <color name="i_am_color_207e">#0000207e</color>
+ <color name="i_am_color_207f">#0000207f</color>
+ <color name="i_am_color_2080">#00002080</color>
+ <color name="i_am_color_2081">#00002081</color>
+ <color name="i_am_color_2082">#00002082</color>
+ <color name="i_am_color_2083">#00002083</color>
+ <color name="i_am_color_2084">#00002084</color>
+ <color name="i_am_color_2085">#00002085</color>
+ <color name="i_am_color_2086">#00002086</color>
+ <color name="i_am_color_2087">#00002087</color>
+ <color name="i_am_color_2088">#00002088</color>
+ <color name="i_am_color_2089">#00002089</color>
+ <color name="i_am_color_208a">#0000208a</color>
+ <color name="i_am_color_208b">#0000208b</color>
+ <color name="i_am_color_208c">#0000208c</color>
+ <color name="i_am_color_208d">#0000208d</color>
+ <color name="i_am_color_208e">#0000208e</color>
+ <color name="i_am_color_208f">#0000208f</color>
+ <color name="i_am_color_2090">#00002090</color>
+ <color name="i_am_color_2091">#00002091</color>
+ <color name="i_am_color_2092">#00002092</color>
+ <color name="i_am_color_2093">#00002093</color>
+ <color name="i_am_color_2094">#00002094</color>
+ <color name="i_am_color_2095">#00002095</color>
+ <color name="i_am_color_2096">#00002096</color>
+ <color name="i_am_color_2097">#00002097</color>
+ <color name="i_am_color_2098">#00002098</color>
+ <color name="i_am_color_2099">#00002099</color>
+ <color name="i_am_color_209a">#0000209a</color>
+ <color name="i_am_color_209b">#0000209b</color>
+ <color name="i_am_color_209c">#0000209c</color>
+ <color name="i_am_color_209d">#0000209d</color>
+ <color name="i_am_color_209e">#0000209e</color>
+ <color name="i_am_color_209f">#0000209f</color>
+ <color name="i_am_color_20a0">#000020a0</color>
+ <color name="i_am_color_20a1">#000020a1</color>
+ <color name="i_am_color_20a2">#000020a2</color>
+ <color name="i_am_color_20a3">#000020a3</color>
+ <color name="i_am_color_20a4">#000020a4</color>
+ <color name="i_am_color_20a5">#000020a5</color>
+ <color name="i_am_color_20a6">#000020a6</color>
+ <color name="i_am_color_20a7">#000020a7</color>
+ <color name="i_am_color_20a8">#000020a8</color>
+ <color name="i_am_color_20a9">#000020a9</color>
+ <color name="i_am_color_20aa">#000020aa</color>
+ <color name="i_am_color_20ab">#000020ab</color>
+ <color name="i_am_color_20ac">#000020ac</color>
+ <color name="i_am_color_20ad">#000020ad</color>
+ <color name="i_am_color_20ae">#000020ae</color>
+ <color name="i_am_color_20af">#000020af</color>
+ <color name="i_am_color_20b0">#000020b0</color>
+ <color name="i_am_color_20b1">#000020b1</color>
+ <color name="i_am_color_20b2">#000020b2</color>
+ <color name="i_am_color_20b3">#000020b3</color>
+ <color name="i_am_color_20b4">#000020b4</color>
+ <color name="i_am_color_20b5">#000020b5</color>
+ <color name="i_am_color_20b6">#000020b6</color>
+ <color name="i_am_color_20b7">#000020b7</color>
+ <color name="i_am_color_20b8">#000020b8</color>
+ <color name="i_am_color_20b9">#000020b9</color>
+ <color name="i_am_color_20ba">#000020ba</color>
+ <color name="i_am_color_20bb">#000020bb</color>
+ <color name="i_am_color_20bc">#000020bc</color>
+ <color name="i_am_color_20bd">#000020bd</color>
+ <color name="i_am_color_20be">#000020be</color>
+ <color name="i_am_color_20bf">#000020bf</color>
+ <color name="i_am_color_20c0">#000020c0</color>
+ <color name="i_am_color_20c1">#000020c1</color>
+ <color name="i_am_color_20c2">#000020c2</color>
+ <color name="i_am_color_20c3">#000020c3</color>
+ <color name="i_am_color_20c4">#000020c4</color>
+ <color name="i_am_color_20c5">#000020c5</color>
+ <color name="i_am_color_20c6">#000020c6</color>
+ <color name="i_am_color_20c7">#000020c7</color>
+ <color name="i_am_color_20c8">#000020c8</color>
+ <color name="i_am_color_20c9">#000020c9</color>
+ <color name="i_am_color_20ca">#000020ca</color>
+ <color name="i_am_color_20cb">#000020cb</color>
+ <color name="i_am_color_20cc">#000020cc</color>
+ <color name="i_am_color_20cd">#000020cd</color>
+ <color name="i_am_color_20ce">#000020ce</color>
+ <color name="i_am_color_20cf">#000020cf</color>
+ <color name="i_am_color_20d0">#000020d0</color>
+ <color name="i_am_color_20d1">#000020d1</color>
+ <color name="i_am_color_20d2">#000020d2</color>
+ <color name="i_am_color_20d3">#000020d3</color>
+ <color name="i_am_color_20d4">#000020d4</color>
+ <color name="i_am_color_20d5">#000020d5</color>
+ <color name="i_am_color_20d6">#000020d6</color>
+ <color name="i_am_color_20d7">#000020d7</color>
+ <color name="i_am_color_20d8">#000020d8</color>
+ <color name="i_am_color_20d9">#000020d9</color>
+ <color name="i_am_color_20da">#000020da</color>
+ <color name="i_am_color_20db">#000020db</color>
+ <color name="i_am_color_20dc">#000020dc</color>
+ <color name="i_am_color_20dd">#000020dd</color>
+ <color name="i_am_color_20de">#000020de</color>
+ <color name="i_am_color_20df">#000020df</color>
+ <color name="i_am_color_20e0">#000020e0</color>
+ <color name="i_am_color_20e1">#000020e1</color>
+ <color name="i_am_color_20e2">#000020e2</color>
+ <color name="i_am_color_20e3">#000020e3</color>
+ <color name="i_am_color_20e4">#000020e4</color>
+ <color name="i_am_color_20e5">#000020e5</color>
+ <color name="i_am_color_20e6">#000020e6</color>
+ <color name="i_am_color_20e7">#000020e7</color>
+ <color name="i_am_color_20e8">#000020e8</color>
+ <color name="i_am_color_20e9">#000020e9</color>
+ <color name="i_am_color_20ea">#000020ea</color>
+ <color name="i_am_color_20eb">#000020eb</color>
+ <color name="i_am_color_20ec">#000020ec</color>
+ <color name="i_am_color_20ed">#000020ed</color>
+ <color name="i_am_color_20ee">#000020ee</color>
+ <color name="i_am_color_20ef">#000020ef</color>
+ <color name="i_am_color_20f0">#000020f0</color>
+ <color name="i_am_color_20f1">#000020f1</color>
+ <color name="i_am_color_20f2">#000020f2</color>
+ <color name="i_am_color_20f3">#000020f3</color>
+ <color name="i_am_color_20f4">#000020f4</color>
+ <color name="i_am_color_20f5">#000020f5</color>
+ <color name="i_am_color_20f6">#000020f6</color>
+ <color name="i_am_color_20f7">#000020f7</color>
+ <color name="i_am_color_20f8">#000020f8</color>
+ <color name="i_am_color_20f9">#000020f9</color>
+ <color name="i_am_color_20fa">#000020fa</color>
+ <color name="i_am_color_20fb">#000020fb</color>
+ <color name="i_am_color_20fc">#000020fc</color>
+ <color name="i_am_color_20fd">#000020fd</color>
+ <color name="i_am_color_20fe">#000020fe</color>
+ <color name="i_am_color_20ff">#000020ff</color>
+ <color name="i_am_color_2100">#00002100</color>
+ <color name="i_am_color_2101">#00002101</color>
+ <color name="i_am_color_2102">#00002102</color>
+ <color name="i_am_color_2103">#00002103</color>
+ <color name="i_am_color_2104">#00002104</color>
+ <color name="i_am_color_2105">#00002105</color>
+ <color name="i_am_color_2106">#00002106</color>
+ <color name="i_am_color_2107">#00002107</color>
+ <color name="i_am_color_2108">#00002108</color>
+ <color name="i_am_color_2109">#00002109</color>
+ <color name="i_am_color_210a">#0000210a</color>
+ <color name="i_am_color_210b">#0000210b</color>
+ <color name="i_am_color_210c">#0000210c</color>
+ <color name="i_am_color_210d">#0000210d</color>
+ <color name="i_am_color_210e">#0000210e</color>
+ <color name="i_am_color_210f">#0000210f</color>
+ <color name="i_am_color_2110">#00002110</color>
+ <color name="i_am_color_2111">#00002111</color>
+ <color name="i_am_color_2112">#00002112</color>
+ <color name="i_am_color_2113">#00002113</color>
+ <color name="i_am_color_2114">#00002114</color>
+ <color name="i_am_color_2115">#00002115</color>
+ <color name="i_am_color_2116">#00002116</color>
+ <color name="i_am_color_2117">#00002117</color>
+ <color name="i_am_color_2118">#00002118</color>
+ <color name="i_am_color_2119">#00002119</color>
+ <color name="i_am_color_211a">#0000211a</color>
+ <color name="i_am_color_211b">#0000211b</color>
+ <color name="i_am_color_211c">#0000211c</color>
+ <color name="i_am_color_211d">#0000211d</color>
+ <color name="i_am_color_211e">#0000211e</color>
+ <color name="i_am_color_211f">#0000211f</color>
+ <color name="i_am_color_2120">#00002120</color>
+ <color name="i_am_color_2121">#00002121</color>
+ <color name="i_am_color_2122">#00002122</color>
+ <color name="i_am_color_2123">#00002123</color>
+ <color name="i_am_color_2124">#00002124</color>
+ <color name="i_am_color_2125">#00002125</color>
+ <color name="i_am_color_2126">#00002126</color>
+ <color name="i_am_color_2127">#00002127</color>
+ <color name="i_am_color_2128">#00002128</color>
+ <color name="i_am_color_2129">#00002129</color>
+ <color name="i_am_color_212a">#0000212a</color>
+ <color name="i_am_color_212b">#0000212b</color>
+ <color name="i_am_color_212c">#0000212c</color>
+ <color name="i_am_color_212d">#0000212d</color>
+ <color name="i_am_color_212e">#0000212e</color>
+ <color name="i_am_color_212f">#0000212f</color>
+ <color name="i_am_color_2130">#00002130</color>
+ <color name="i_am_color_2131">#00002131</color>
+ <color name="i_am_color_2132">#00002132</color>
+ <color name="i_am_color_2133">#00002133</color>
+ <color name="i_am_color_2134">#00002134</color>
+ <color name="i_am_color_2135">#00002135</color>
+ <color name="i_am_color_2136">#00002136</color>
+ <color name="i_am_color_2137">#00002137</color>
+ <color name="i_am_color_2138">#00002138</color>
+ <color name="i_am_color_2139">#00002139</color>
+ <color name="i_am_color_213a">#0000213a</color>
+ <color name="i_am_color_213b">#0000213b</color>
+ <color name="i_am_color_213c">#0000213c</color>
+ <color name="i_am_color_213d">#0000213d</color>
+ <color name="i_am_color_213e">#0000213e</color>
+ <color name="i_am_color_213f">#0000213f</color>
+ <color name="i_am_color_2140">#00002140</color>
+ <color name="i_am_color_2141">#00002141</color>
+ <color name="i_am_color_2142">#00002142</color>
+ <color name="i_am_color_2143">#00002143</color>
+ <color name="i_am_color_2144">#00002144</color>
+ <color name="i_am_color_2145">#00002145</color>
+ <color name="i_am_color_2146">#00002146</color>
+ <color name="i_am_color_2147">#00002147</color>
+ <color name="i_am_color_2148">#00002148</color>
+ <color name="i_am_color_2149">#00002149</color>
+ <color name="i_am_color_214a">#0000214a</color>
+ <color name="i_am_color_214b">#0000214b</color>
+ <color name="i_am_color_214c">#0000214c</color>
+ <color name="i_am_color_214d">#0000214d</color>
+ <color name="i_am_color_214e">#0000214e</color>
+ <color name="i_am_color_214f">#0000214f</color>
+ <color name="i_am_color_2150">#00002150</color>
+ <color name="i_am_color_2151">#00002151</color>
+ <color name="i_am_color_2152">#00002152</color>
+ <color name="i_am_color_2153">#00002153</color>
+ <color name="i_am_color_2154">#00002154</color>
+ <color name="i_am_color_2155">#00002155</color>
+ <color name="i_am_color_2156">#00002156</color>
+ <color name="i_am_color_2157">#00002157</color>
+ <color name="i_am_color_2158">#00002158</color>
+ <color name="i_am_color_2159">#00002159</color>
+ <color name="i_am_color_215a">#0000215a</color>
+ <color name="i_am_color_215b">#0000215b</color>
+ <color name="i_am_color_215c">#0000215c</color>
+ <color name="i_am_color_215d">#0000215d</color>
+ <color name="i_am_color_215e">#0000215e</color>
+ <color name="i_am_color_215f">#0000215f</color>
+ <color name="i_am_color_2160">#00002160</color>
+ <color name="i_am_color_2161">#00002161</color>
+ <color name="i_am_color_2162">#00002162</color>
+ <color name="i_am_color_2163">#00002163</color>
+ <color name="i_am_color_2164">#00002164</color>
+ <color name="i_am_color_2165">#00002165</color>
+ <color name="i_am_color_2166">#00002166</color>
+ <color name="i_am_color_2167">#00002167</color>
+ <color name="i_am_color_2168">#00002168</color>
+ <color name="i_am_color_2169">#00002169</color>
+ <color name="i_am_color_216a">#0000216a</color>
+ <color name="i_am_color_216b">#0000216b</color>
+ <color name="i_am_color_216c">#0000216c</color>
+ <color name="i_am_color_216d">#0000216d</color>
+ <color name="i_am_color_216e">#0000216e</color>
+ <color name="i_am_color_216f">#0000216f</color>
+ <color name="i_am_color_2170">#00002170</color>
+ <color name="i_am_color_2171">#00002171</color>
+ <color name="i_am_color_2172">#00002172</color>
+ <color name="i_am_color_2173">#00002173</color>
+ <color name="i_am_color_2174">#00002174</color>
+ <color name="i_am_color_2175">#00002175</color>
+ <color name="i_am_color_2176">#00002176</color>
+ <color name="i_am_color_2177">#00002177</color>
+ <color name="i_am_color_2178">#00002178</color>
+ <color name="i_am_color_2179">#00002179</color>
+ <color name="i_am_color_217a">#0000217a</color>
+ <color name="i_am_color_217b">#0000217b</color>
+ <color name="i_am_color_217c">#0000217c</color>
+ <color name="i_am_color_217d">#0000217d</color>
+ <color name="i_am_color_217e">#0000217e</color>
+ <color name="i_am_color_217f">#0000217f</color>
+ <color name="i_am_color_2180">#00002180</color>
+ <color name="i_am_color_2181">#00002181</color>
+ <color name="i_am_color_2182">#00002182</color>
+ <color name="i_am_color_2183">#00002183</color>
+ <color name="i_am_color_2184">#00002184</color>
+ <color name="i_am_color_2185">#00002185</color>
+ <color name="i_am_color_2186">#00002186</color>
+ <color name="i_am_color_2187">#00002187</color>
+ <color name="i_am_color_2188">#00002188</color>
+ <color name="i_am_color_2189">#00002189</color>
+ <color name="i_am_color_218a">#0000218a</color>
+ <color name="i_am_color_218b">#0000218b</color>
+ <color name="i_am_color_218c">#0000218c</color>
+ <color name="i_am_color_218d">#0000218d</color>
+ <color name="i_am_color_218e">#0000218e</color>
+ <color name="i_am_color_218f">#0000218f</color>
+ <color name="i_am_color_2190">#00002190</color>
+ <color name="i_am_color_2191">#00002191</color>
+ <color name="i_am_color_2192">#00002192</color>
+ <color name="i_am_color_2193">#00002193</color>
+ <color name="i_am_color_2194">#00002194</color>
+ <color name="i_am_color_2195">#00002195</color>
+ <color name="i_am_color_2196">#00002196</color>
+ <color name="i_am_color_2197">#00002197</color>
+ <color name="i_am_color_2198">#00002198</color>
+ <color name="i_am_color_2199">#00002199</color>
+ <color name="i_am_color_219a">#0000219a</color>
+ <color name="i_am_color_219b">#0000219b</color>
+ <color name="i_am_color_219c">#0000219c</color>
+ <color name="i_am_color_219d">#0000219d</color>
+ <color name="i_am_color_219e">#0000219e</color>
+ <color name="i_am_color_219f">#0000219f</color>
+ <color name="i_am_color_21a0">#000021a0</color>
+ <color name="i_am_color_21a1">#000021a1</color>
+ <color name="i_am_color_21a2">#000021a2</color>
+ <color name="i_am_color_21a3">#000021a3</color>
+ <color name="i_am_color_21a4">#000021a4</color>
+ <color name="i_am_color_21a5">#000021a5</color>
+ <color name="i_am_color_21a6">#000021a6</color>
+ <color name="i_am_color_21a7">#000021a7</color>
+ <color name="i_am_color_21a8">#000021a8</color>
+ <color name="i_am_color_21a9">#000021a9</color>
+ <color name="i_am_color_21aa">#000021aa</color>
+ <color name="i_am_color_21ab">#000021ab</color>
+ <color name="i_am_color_21ac">#000021ac</color>
+ <color name="i_am_color_21ad">#000021ad</color>
+ <color name="i_am_color_21ae">#000021ae</color>
+ <color name="i_am_color_21af">#000021af</color>
+ <color name="i_am_color_21b0">#000021b0</color>
+ <color name="i_am_color_21b1">#000021b1</color>
+ <color name="i_am_color_21b2">#000021b2</color>
+ <color name="i_am_color_21b3">#000021b3</color>
+ <color name="i_am_color_21b4">#000021b4</color>
+ <color name="i_am_color_21b5">#000021b5</color>
+ <color name="i_am_color_21b6">#000021b6</color>
+ <color name="i_am_color_21b7">#000021b7</color>
+ <color name="i_am_color_21b8">#000021b8</color>
+ <color name="i_am_color_21b9">#000021b9</color>
+ <color name="i_am_color_21ba">#000021ba</color>
+ <color name="i_am_color_21bb">#000021bb</color>
+ <color name="i_am_color_21bc">#000021bc</color>
+ <color name="i_am_color_21bd">#000021bd</color>
+ <color name="i_am_color_21be">#000021be</color>
+ <color name="i_am_color_21bf">#000021bf</color>
+ <color name="i_am_color_21c0">#000021c0</color>
+ <color name="i_am_color_21c1">#000021c1</color>
+ <color name="i_am_color_21c2">#000021c2</color>
+ <color name="i_am_color_21c3">#000021c3</color>
+ <color name="i_am_color_21c4">#000021c4</color>
+ <color name="i_am_color_21c5">#000021c5</color>
+ <color name="i_am_color_21c6">#000021c6</color>
+ <color name="i_am_color_21c7">#000021c7</color>
+ <color name="i_am_color_21c8">#000021c8</color>
+ <color name="i_am_color_21c9">#000021c9</color>
+ <color name="i_am_color_21ca">#000021ca</color>
+ <color name="i_am_color_21cb">#000021cb</color>
+ <color name="i_am_color_21cc">#000021cc</color>
+ <color name="i_am_color_21cd">#000021cd</color>
+ <color name="i_am_color_21ce">#000021ce</color>
+ <color name="i_am_color_21cf">#000021cf</color>
+ <color name="i_am_color_21d0">#000021d0</color>
+ <color name="i_am_color_21d1">#000021d1</color>
+ <color name="i_am_color_21d2">#000021d2</color>
+ <color name="i_am_color_21d3">#000021d3</color>
+ <color name="i_am_color_21d4">#000021d4</color>
+ <color name="i_am_color_21d5">#000021d5</color>
+ <color name="i_am_color_21d6">#000021d6</color>
+ <color name="i_am_color_21d7">#000021d7</color>
+ <color name="i_am_color_21d8">#000021d8</color>
+ <color name="i_am_color_21d9">#000021d9</color>
+ <color name="i_am_color_21da">#000021da</color>
+ <color name="i_am_color_21db">#000021db</color>
+ <color name="i_am_color_21dc">#000021dc</color>
+ <color name="i_am_color_21dd">#000021dd</color>
+ <color name="i_am_color_21de">#000021de</color>
+ <color name="i_am_color_21df">#000021df</color>
+ <color name="i_am_color_21e0">#000021e0</color>
+ <color name="i_am_color_21e1">#000021e1</color>
+ <color name="i_am_color_21e2">#000021e2</color>
+ <color name="i_am_color_21e3">#000021e3</color>
+ <color name="i_am_color_21e4">#000021e4</color>
+ <color name="i_am_color_21e5">#000021e5</color>
+ <color name="i_am_color_21e6">#000021e6</color>
+ <color name="i_am_color_21e7">#000021e7</color>
+ <color name="i_am_color_21e8">#000021e8</color>
+ <color name="i_am_color_21e9">#000021e9</color>
+ <color name="i_am_color_21ea">#000021ea</color>
+ <color name="i_am_color_21eb">#000021eb</color>
+ <color name="i_am_color_21ec">#000021ec</color>
+ <color name="i_am_color_21ed">#000021ed</color>
+ <color name="i_am_color_21ee">#000021ee</color>
+ <color name="i_am_color_21ef">#000021ef</color>
+ <color name="i_am_color_21f0">#000021f0</color>
+ <color name="i_am_color_21f1">#000021f1</color>
+ <color name="i_am_color_21f2">#000021f2</color>
+ <color name="i_am_color_21f3">#000021f3</color>
+ <color name="i_am_color_21f4">#000021f4</color>
+ <color name="i_am_color_21f5">#000021f5</color>
+ <color name="i_am_color_21f6">#000021f6</color>
+ <color name="i_am_color_21f7">#000021f7</color>
+ <color name="i_am_color_21f8">#000021f8</color>
+ <color name="i_am_color_21f9">#000021f9</color>
+ <color name="i_am_color_21fa">#000021fa</color>
+ <color name="i_am_color_21fb">#000021fb</color>
+ <color name="i_am_color_21fc">#000021fc</color>
+ <color name="i_am_color_21fd">#000021fd</color>
+ <color name="i_am_color_21fe">#000021fe</color>
+ <color name="i_am_color_21ff">#000021ff</color>
+ <color name="i_am_color_2200">#00002200</color>
+ <color name="i_am_color_2201">#00002201</color>
+ <color name="i_am_color_2202">#00002202</color>
+ <color name="i_am_color_2203">#00002203</color>
+ <color name="i_am_color_2204">#00002204</color>
+ <color name="i_am_color_2205">#00002205</color>
+ <color name="i_am_color_2206">#00002206</color>
+ <color name="i_am_color_2207">#00002207</color>
+ <color name="i_am_color_2208">#00002208</color>
+ <color name="i_am_color_2209">#00002209</color>
+ <color name="i_am_color_220a">#0000220a</color>
+ <color name="i_am_color_220b">#0000220b</color>
+ <color name="i_am_color_220c">#0000220c</color>
+ <color name="i_am_color_220d">#0000220d</color>
+ <color name="i_am_color_220e">#0000220e</color>
+ <color name="i_am_color_220f">#0000220f</color>
+ <color name="i_am_color_2210">#00002210</color>
+ <color name="i_am_color_2211">#00002211</color>
+ <color name="i_am_color_2212">#00002212</color>
+ <color name="i_am_color_2213">#00002213</color>
+ <color name="i_am_color_2214">#00002214</color>
+ <color name="i_am_color_2215">#00002215</color>
+ <color name="i_am_color_2216">#00002216</color>
+ <color name="i_am_color_2217">#00002217</color>
+ <color name="i_am_color_2218">#00002218</color>
+ <color name="i_am_color_2219">#00002219</color>
+ <color name="i_am_color_221a">#0000221a</color>
+ <color name="i_am_color_221b">#0000221b</color>
+ <color name="i_am_color_221c">#0000221c</color>
+ <color name="i_am_color_221d">#0000221d</color>
+ <color name="i_am_color_221e">#0000221e</color>
+ <color name="i_am_color_221f">#0000221f</color>
+ <color name="i_am_color_2220">#00002220</color>
+ <color name="i_am_color_2221">#00002221</color>
+ <color name="i_am_color_2222">#00002222</color>
+ <color name="i_am_color_2223">#00002223</color>
+ <color name="i_am_color_2224">#00002224</color>
+ <color name="i_am_color_2225">#00002225</color>
+ <color name="i_am_color_2226">#00002226</color>
+ <color name="i_am_color_2227">#00002227</color>
+ <color name="i_am_color_2228">#00002228</color>
+ <color name="i_am_color_2229">#00002229</color>
+ <color name="i_am_color_222a">#0000222a</color>
+ <color name="i_am_color_222b">#0000222b</color>
+ <color name="i_am_color_222c">#0000222c</color>
+ <color name="i_am_color_222d">#0000222d</color>
+ <color name="i_am_color_222e">#0000222e</color>
+ <color name="i_am_color_222f">#0000222f</color>
+ <color name="i_am_color_2230">#00002230</color>
+ <color name="i_am_color_2231">#00002231</color>
+ <color name="i_am_color_2232">#00002232</color>
+ <color name="i_am_color_2233">#00002233</color>
+ <color name="i_am_color_2234">#00002234</color>
+ <color name="i_am_color_2235">#00002235</color>
+ <color name="i_am_color_2236">#00002236</color>
+ <color name="i_am_color_2237">#00002237</color>
+ <color name="i_am_color_2238">#00002238</color>
+ <color name="i_am_color_2239">#00002239</color>
+ <color name="i_am_color_223a">#0000223a</color>
+ <color name="i_am_color_223b">#0000223b</color>
+ <color name="i_am_color_223c">#0000223c</color>
+ <color name="i_am_color_223d">#0000223d</color>
+ <color name="i_am_color_223e">#0000223e</color>
+ <color name="i_am_color_223f">#0000223f</color>
+ <color name="i_am_color_2240">#00002240</color>
+ <color name="i_am_color_2241">#00002241</color>
+ <color name="i_am_color_2242">#00002242</color>
+ <color name="i_am_color_2243">#00002243</color>
+ <color name="i_am_color_2244">#00002244</color>
+ <color name="i_am_color_2245">#00002245</color>
+ <color name="i_am_color_2246">#00002246</color>
+ <color name="i_am_color_2247">#00002247</color>
+ <color name="i_am_color_2248">#00002248</color>
+ <color name="i_am_color_2249">#00002249</color>
+ <color name="i_am_color_224a">#0000224a</color>
+ <color name="i_am_color_224b">#0000224b</color>
+ <color name="i_am_color_224c">#0000224c</color>
+ <color name="i_am_color_224d">#0000224d</color>
+ <color name="i_am_color_224e">#0000224e</color>
+ <color name="i_am_color_224f">#0000224f</color>
+ <color name="i_am_color_2250">#00002250</color>
+ <color name="i_am_color_2251">#00002251</color>
+ <color name="i_am_color_2252">#00002252</color>
+ <color name="i_am_color_2253">#00002253</color>
+ <color name="i_am_color_2254">#00002254</color>
+ <color name="i_am_color_2255">#00002255</color>
+ <color name="i_am_color_2256">#00002256</color>
+ <color name="i_am_color_2257">#00002257</color>
+ <color name="i_am_color_2258">#00002258</color>
+ <color name="i_am_color_2259">#00002259</color>
+ <color name="i_am_color_225a">#0000225a</color>
+ <color name="i_am_color_225b">#0000225b</color>
+ <color name="i_am_color_225c">#0000225c</color>
+ <color name="i_am_color_225d">#0000225d</color>
+ <color name="i_am_color_225e">#0000225e</color>
+ <color name="i_am_color_225f">#0000225f</color>
+ <color name="i_am_color_2260">#00002260</color>
+ <color name="i_am_color_2261">#00002261</color>
+ <color name="i_am_color_2262">#00002262</color>
+ <color name="i_am_color_2263">#00002263</color>
+ <color name="i_am_color_2264">#00002264</color>
+ <color name="i_am_color_2265">#00002265</color>
+ <color name="i_am_color_2266">#00002266</color>
+ <color name="i_am_color_2267">#00002267</color>
+ <color name="i_am_color_2268">#00002268</color>
+ <color name="i_am_color_2269">#00002269</color>
+ <color name="i_am_color_226a">#0000226a</color>
+ <color name="i_am_color_226b">#0000226b</color>
+ <color name="i_am_color_226c">#0000226c</color>
+ <color name="i_am_color_226d">#0000226d</color>
+ <color name="i_am_color_226e">#0000226e</color>
+ <color name="i_am_color_226f">#0000226f</color>
+ <color name="i_am_color_2270">#00002270</color>
+ <color name="i_am_color_2271">#00002271</color>
+ <color name="i_am_color_2272">#00002272</color>
+ <color name="i_am_color_2273">#00002273</color>
+ <color name="i_am_color_2274">#00002274</color>
+ <color name="i_am_color_2275">#00002275</color>
+ <color name="i_am_color_2276">#00002276</color>
+ <color name="i_am_color_2277">#00002277</color>
+ <color name="i_am_color_2278">#00002278</color>
+ <color name="i_am_color_2279">#00002279</color>
+ <color name="i_am_color_227a">#0000227a</color>
+ <color name="i_am_color_227b">#0000227b</color>
+ <color name="i_am_color_227c">#0000227c</color>
+ <color name="i_am_color_227d">#0000227d</color>
+ <color name="i_am_color_227e">#0000227e</color>
+ <color name="i_am_color_227f">#0000227f</color>
+ <color name="i_am_color_2280">#00002280</color>
+ <color name="i_am_color_2281">#00002281</color>
+ <color name="i_am_color_2282">#00002282</color>
+ <color name="i_am_color_2283">#00002283</color>
+ <color name="i_am_color_2284">#00002284</color>
+ <color name="i_am_color_2285">#00002285</color>
+ <color name="i_am_color_2286">#00002286</color>
+ <color name="i_am_color_2287">#00002287</color>
+ <color name="i_am_color_2288">#00002288</color>
+ <color name="i_am_color_2289">#00002289</color>
+ <color name="i_am_color_228a">#0000228a</color>
+ <color name="i_am_color_228b">#0000228b</color>
+ <color name="i_am_color_228c">#0000228c</color>
+ <color name="i_am_color_228d">#0000228d</color>
+ <color name="i_am_color_228e">#0000228e</color>
+ <color name="i_am_color_228f">#0000228f</color>
+ <color name="i_am_color_2290">#00002290</color>
+ <color name="i_am_color_2291">#00002291</color>
+ <color name="i_am_color_2292">#00002292</color>
+ <color name="i_am_color_2293">#00002293</color>
+ <color name="i_am_color_2294">#00002294</color>
+ <color name="i_am_color_2295">#00002295</color>
+ <color name="i_am_color_2296">#00002296</color>
+ <color name="i_am_color_2297">#00002297</color>
+ <color name="i_am_color_2298">#00002298</color>
+ <color name="i_am_color_2299">#00002299</color>
+ <color name="i_am_color_229a">#0000229a</color>
+ <color name="i_am_color_229b">#0000229b</color>
+ <color name="i_am_color_229c">#0000229c</color>
+ <color name="i_am_color_229d">#0000229d</color>
+ <color name="i_am_color_229e">#0000229e</color>
+ <color name="i_am_color_229f">#0000229f</color>
+ <color name="i_am_color_22a0">#000022a0</color>
+ <color name="i_am_color_22a1">#000022a1</color>
+ <color name="i_am_color_22a2">#000022a2</color>
+ <color name="i_am_color_22a3">#000022a3</color>
+ <color name="i_am_color_22a4">#000022a4</color>
+ <color name="i_am_color_22a5">#000022a5</color>
+ <color name="i_am_color_22a6">#000022a6</color>
+ <color name="i_am_color_22a7">#000022a7</color>
+ <color name="i_am_color_22a8">#000022a8</color>
+ <color name="i_am_color_22a9">#000022a9</color>
+ <color name="i_am_color_22aa">#000022aa</color>
+ <color name="i_am_color_22ab">#000022ab</color>
+ <color name="i_am_color_22ac">#000022ac</color>
+ <color name="i_am_color_22ad">#000022ad</color>
+ <color name="i_am_color_22ae">#000022ae</color>
+ <color name="i_am_color_22af">#000022af</color>
+ <color name="i_am_color_22b0">#000022b0</color>
+ <color name="i_am_color_22b1">#000022b1</color>
+ <color name="i_am_color_22b2">#000022b2</color>
+ <color name="i_am_color_22b3">#000022b3</color>
+ <color name="i_am_color_22b4">#000022b4</color>
+ <color name="i_am_color_22b5">#000022b5</color>
+ <color name="i_am_color_22b6">#000022b6</color>
+ <color name="i_am_color_22b7">#000022b7</color>
+ <color name="i_am_color_22b8">#000022b8</color>
+ <color name="i_am_color_22b9">#000022b9</color>
+ <color name="i_am_color_22ba">#000022ba</color>
+ <color name="i_am_color_22bb">#000022bb</color>
+ <color name="i_am_color_22bc">#000022bc</color>
+ <color name="i_am_color_22bd">#000022bd</color>
+ <color name="i_am_color_22be">#000022be</color>
+ <color name="i_am_color_22bf">#000022bf</color>
+ <color name="i_am_color_22c0">#000022c0</color>
+ <color name="i_am_color_22c1">#000022c1</color>
+ <color name="i_am_color_22c2">#000022c2</color>
+ <color name="i_am_color_22c3">#000022c3</color>
+ <color name="i_am_color_22c4">#000022c4</color>
+ <color name="i_am_color_22c5">#000022c5</color>
+ <color name="i_am_color_22c6">#000022c6</color>
+ <color name="i_am_color_22c7">#000022c7</color>
+ <color name="i_am_color_22c8">#000022c8</color>
+ <color name="i_am_color_22c9">#000022c9</color>
+ <color name="i_am_color_22ca">#000022ca</color>
+ <color name="i_am_color_22cb">#000022cb</color>
+ <color name="i_am_color_22cc">#000022cc</color>
+ <color name="i_am_color_22cd">#000022cd</color>
+ <color name="i_am_color_22ce">#000022ce</color>
+ <color name="i_am_color_22cf">#000022cf</color>
+ <color name="i_am_color_22d0">#000022d0</color>
+ <color name="i_am_color_22d1">#000022d1</color>
+ <color name="i_am_color_22d2">#000022d2</color>
+ <color name="i_am_color_22d3">#000022d3</color>
+ <color name="i_am_color_22d4">#000022d4</color>
+ <color name="i_am_color_22d5">#000022d5</color>
+ <color name="i_am_color_22d6">#000022d6</color>
+ <color name="i_am_color_22d7">#000022d7</color>
+ <color name="i_am_color_22d8">#000022d8</color>
+ <color name="i_am_color_22d9">#000022d9</color>
+ <color name="i_am_color_22da">#000022da</color>
+ <color name="i_am_color_22db">#000022db</color>
+ <color name="i_am_color_22dc">#000022dc</color>
+ <color name="i_am_color_22dd">#000022dd</color>
+ <color name="i_am_color_22de">#000022de</color>
+ <color name="i_am_color_22df">#000022df</color>
+ <color name="i_am_color_22e0">#000022e0</color>
+ <color name="i_am_color_22e1">#000022e1</color>
+ <color name="i_am_color_22e2">#000022e2</color>
+ <color name="i_am_color_22e3">#000022e3</color>
+ <color name="i_am_color_22e4">#000022e4</color>
+ <color name="i_am_color_22e5">#000022e5</color>
+ <color name="i_am_color_22e6">#000022e6</color>
+ <color name="i_am_color_22e7">#000022e7</color>
+ <color name="i_am_color_22e8">#000022e8</color>
+ <color name="i_am_color_22e9">#000022e9</color>
+ <color name="i_am_color_22ea">#000022ea</color>
+ <color name="i_am_color_22eb">#000022eb</color>
+ <color name="i_am_color_22ec">#000022ec</color>
+ <color name="i_am_color_22ed">#000022ed</color>
+ <color name="i_am_color_22ee">#000022ee</color>
+ <color name="i_am_color_22ef">#000022ef</color>
+ <color name="i_am_color_22f0">#000022f0</color>
+ <color name="i_am_color_22f1">#000022f1</color>
+ <color name="i_am_color_22f2">#000022f2</color>
+ <color name="i_am_color_22f3">#000022f3</color>
+ <color name="i_am_color_22f4">#000022f4</color>
+ <color name="i_am_color_22f5">#000022f5</color>
+ <color name="i_am_color_22f6">#000022f6</color>
+ <color name="i_am_color_22f7">#000022f7</color>
+ <color name="i_am_color_22f8">#000022f8</color>
+ <color name="i_am_color_22f9">#000022f9</color>
+ <color name="i_am_color_22fa">#000022fa</color>
+ <color name="i_am_color_22fb">#000022fb</color>
+ <color name="i_am_color_22fc">#000022fc</color>
+ <color name="i_am_color_22fd">#000022fd</color>
+ <color name="i_am_color_22fe">#000022fe</color>
+ <color name="i_am_color_22ff">#000022ff</color>
+ <color name="i_am_color_2300">#00002300</color>
+ <color name="i_am_color_2301">#00002301</color>
+ <color name="i_am_color_2302">#00002302</color>
+ <color name="i_am_color_2303">#00002303</color>
+ <color name="i_am_color_2304">#00002304</color>
+ <color name="i_am_color_2305">#00002305</color>
+ <color name="i_am_color_2306">#00002306</color>
+ <color name="i_am_color_2307">#00002307</color>
+ <color name="i_am_color_2308">#00002308</color>
+ <color name="i_am_color_2309">#00002309</color>
+ <color name="i_am_color_230a">#0000230a</color>
+ <color name="i_am_color_230b">#0000230b</color>
+ <color name="i_am_color_230c">#0000230c</color>
+ <color name="i_am_color_230d">#0000230d</color>
+ <color name="i_am_color_230e">#0000230e</color>
+ <color name="i_am_color_230f">#0000230f</color>
+ <color name="i_am_color_2310">#00002310</color>
+ <color name="i_am_color_2311">#00002311</color>
+ <color name="i_am_color_2312">#00002312</color>
+ <color name="i_am_color_2313">#00002313</color>
+ <color name="i_am_color_2314">#00002314</color>
+ <color name="i_am_color_2315">#00002315</color>
+ <color name="i_am_color_2316">#00002316</color>
+ <color name="i_am_color_2317">#00002317</color>
+ <color name="i_am_color_2318">#00002318</color>
+ <color name="i_am_color_2319">#00002319</color>
+ <color name="i_am_color_231a">#0000231a</color>
+ <color name="i_am_color_231b">#0000231b</color>
+ <color name="i_am_color_231c">#0000231c</color>
+ <color name="i_am_color_231d">#0000231d</color>
+ <color name="i_am_color_231e">#0000231e</color>
+ <color name="i_am_color_231f">#0000231f</color>
+ <color name="i_am_color_2320">#00002320</color>
+ <color name="i_am_color_2321">#00002321</color>
+ <color name="i_am_color_2322">#00002322</color>
+ <color name="i_am_color_2323">#00002323</color>
+ <color name="i_am_color_2324">#00002324</color>
+ <color name="i_am_color_2325">#00002325</color>
+ <color name="i_am_color_2326">#00002326</color>
+ <color name="i_am_color_2327">#00002327</color>
+ <color name="i_am_color_2328">#00002328</color>
+ <color name="i_am_color_2329">#00002329</color>
+ <color name="i_am_color_232a">#0000232a</color>
+ <color name="i_am_color_232b">#0000232b</color>
+ <color name="i_am_color_232c">#0000232c</color>
+ <color name="i_am_color_232d">#0000232d</color>
+ <color name="i_am_color_232e">#0000232e</color>
+ <color name="i_am_color_232f">#0000232f</color>
+ <color name="i_am_color_2330">#00002330</color>
+ <color name="i_am_color_2331">#00002331</color>
+ <color name="i_am_color_2332">#00002332</color>
+ <color name="i_am_color_2333">#00002333</color>
+ <color name="i_am_color_2334">#00002334</color>
+ <color name="i_am_color_2335">#00002335</color>
+ <color name="i_am_color_2336">#00002336</color>
+ <color name="i_am_color_2337">#00002337</color>
+ <color name="i_am_color_2338">#00002338</color>
+ <color name="i_am_color_2339">#00002339</color>
+ <color name="i_am_color_233a">#0000233a</color>
+ <color name="i_am_color_233b">#0000233b</color>
+ <color name="i_am_color_233c">#0000233c</color>
+ <color name="i_am_color_233d">#0000233d</color>
+ <color name="i_am_color_233e">#0000233e</color>
+ <color name="i_am_color_233f">#0000233f</color>
+ <color name="i_am_color_2340">#00002340</color>
+ <color name="i_am_color_2341">#00002341</color>
+ <color name="i_am_color_2342">#00002342</color>
+ <color name="i_am_color_2343">#00002343</color>
+ <color name="i_am_color_2344">#00002344</color>
+ <color name="i_am_color_2345">#00002345</color>
+ <color name="i_am_color_2346">#00002346</color>
+ <color name="i_am_color_2347">#00002347</color>
+ <color name="i_am_color_2348">#00002348</color>
+ <color name="i_am_color_2349">#00002349</color>
+ <color name="i_am_color_234a">#0000234a</color>
+ <color name="i_am_color_234b">#0000234b</color>
+ <color name="i_am_color_234c">#0000234c</color>
+ <color name="i_am_color_234d">#0000234d</color>
+ <color name="i_am_color_234e">#0000234e</color>
+ <color name="i_am_color_234f">#0000234f</color>
+ <color name="i_am_color_2350">#00002350</color>
+ <color name="i_am_color_2351">#00002351</color>
+ <color name="i_am_color_2352">#00002352</color>
+ <color name="i_am_color_2353">#00002353</color>
+ <color name="i_am_color_2354">#00002354</color>
+ <color name="i_am_color_2355">#00002355</color>
+ <color name="i_am_color_2356">#00002356</color>
+ <color name="i_am_color_2357">#00002357</color>
+ <color name="i_am_color_2358">#00002358</color>
+ <color name="i_am_color_2359">#00002359</color>
+ <color name="i_am_color_235a">#0000235a</color>
+ <color name="i_am_color_235b">#0000235b</color>
+ <color name="i_am_color_235c">#0000235c</color>
+ <color name="i_am_color_235d">#0000235d</color>
+ <color name="i_am_color_235e">#0000235e</color>
+ <color name="i_am_color_235f">#0000235f</color>
+ <color name="i_am_color_2360">#00002360</color>
+ <color name="i_am_color_2361">#00002361</color>
+ <color name="i_am_color_2362">#00002362</color>
+ <color name="i_am_color_2363">#00002363</color>
+ <color name="i_am_color_2364">#00002364</color>
+ <color name="i_am_color_2365">#00002365</color>
+ <color name="i_am_color_2366">#00002366</color>
+ <color name="i_am_color_2367">#00002367</color>
+ <color name="i_am_color_2368">#00002368</color>
+ <color name="i_am_color_2369">#00002369</color>
+ <color name="i_am_color_236a">#0000236a</color>
+ <color name="i_am_color_236b">#0000236b</color>
+ <color name="i_am_color_236c">#0000236c</color>
+ <color name="i_am_color_236d">#0000236d</color>
+ <color name="i_am_color_236e">#0000236e</color>
+ <color name="i_am_color_236f">#0000236f</color>
+ <color name="i_am_color_2370">#00002370</color>
+ <color name="i_am_color_2371">#00002371</color>
+ <color name="i_am_color_2372">#00002372</color>
+ <color name="i_am_color_2373">#00002373</color>
+ <color name="i_am_color_2374">#00002374</color>
+ <color name="i_am_color_2375">#00002375</color>
+ <color name="i_am_color_2376">#00002376</color>
+ <color name="i_am_color_2377">#00002377</color>
+ <color name="i_am_color_2378">#00002378</color>
+ <color name="i_am_color_2379">#00002379</color>
+ <color name="i_am_color_237a">#0000237a</color>
+ <color name="i_am_color_237b">#0000237b</color>
+ <color name="i_am_color_237c">#0000237c</color>
+ <color name="i_am_color_237d">#0000237d</color>
+ <color name="i_am_color_237e">#0000237e</color>
+ <color name="i_am_color_237f">#0000237f</color>
+ <color name="i_am_color_2380">#00002380</color>
+ <color name="i_am_color_2381">#00002381</color>
+ <color name="i_am_color_2382">#00002382</color>
+ <color name="i_am_color_2383">#00002383</color>
+ <color name="i_am_color_2384">#00002384</color>
+ <color name="i_am_color_2385">#00002385</color>
+ <color name="i_am_color_2386">#00002386</color>
+ <color name="i_am_color_2387">#00002387</color>
+ <color name="i_am_color_2388">#00002388</color>
+ <color name="i_am_color_2389">#00002389</color>
+ <color name="i_am_color_238a">#0000238a</color>
+ <color name="i_am_color_238b">#0000238b</color>
+ <color name="i_am_color_238c">#0000238c</color>
+ <color name="i_am_color_238d">#0000238d</color>
+ <color name="i_am_color_238e">#0000238e</color>
+ <color name="i_am_color_238f">#0000238f</color>
+ <color name="i_am_color_2390">#00002390</color>
+ <color name="i_am_color_2391">#00002391</color>
+ <color name="i_am_color_2392">#00002392</color>
+ <color name="i_am_color_2393">#00002393</color>
+ <color name="i_am_color_2394">#00002394</color>
+ <color name="i_am_color_2395">#00002395</color>
+ <color name="i_am_color_2396">#00002396</color>
+ <color name="i_am_color_2397">#00002397</color>
+ <color name="i_am_color_2398">#00002398</color>
+ <color name="i_am_color_2399">#00002399</color>
+ <color name="i_am_color_239a">#0000239a</color>
+ <color name="i_am_color_239b">#0000239b</color>
+ <color name="i_am_color_239c">#0000239c</color>
+ <color name="i_am_color_239d">#0000239d</color>
+ <color name="i_am_color_239e">#0000239e</color>
+ <color name="i_am_color_239f">#0000239f</color>
+ <color name="i_am_color_23a0">#000023a0</color>
+ <color name="i_am_color_23a1">#000023a1</color>
+ <color name="i_am_color_23a2">#000023a2</color>
+ <color name="i_am_color_23a3">#000023a3</color>
+ <color name="i_am_color_23a4">#000023a4</color>
+ <color name="i_am_color_23a5">#000023a5</color>
+ <color name="i_am_color_23a6">#000023a6</color>
+ <color name="i_am_color_23a7">#000023a7</color>
+ <color name="i_am_color_23a8">#000023a8</color>
+ <color name="i_am_color_23a9">#000023a9</color>
+ <color name="i_am_color_23aa">#000023aa</color>
+ <color name="i_am_color_23ab">#000023ab</color>
+ <color name="i_am_color_23ac">#000023ac</color>
+ <color name="i_am_color_23ad">#000023ad</color>
+ <color name="i_am_color_23ae">#000023ae</color>
+ <color name="i_am_color_23af">#000023af</color>
+ <color name="i_am_color_23b0">#000023b0</color>
+ <color name="i_am_color_23b1">#000023b1</color>
+ <color name="i_am_color_23b2">#000023b2</color>
+ <color name="i_am_color_23b3">#000023b3</color>
+ <color name="i_am_color_23b4">#000023b4</color>
+ <color name="i_am_color_23b5">#000023b5</color>
+ <color name="i_am_color_23b6">#000023b6</color>
+ <color name="i_am_color_23b7">#000023b7</color>
+ <color name="i_am_color_23b8">#000023b8</color>
+ <color name="i_am_color_23b9">#000023b9</color>
+ <color name="i_am_color_23ba">#000023ba</color>
+ <color name="i_am_color_23bb">#000023bb</color>
+ <color name="i_am_color_23bc">#000023bc</color>
+ <color name="i_am_color_23bd">#000023bd</color>
+ <color name="i_am_color_23be">#000023be</color>
+ <color name="i_am_color_23bf">#000023bf</color>
+ <color name="i_am_color_23c0">#000023c0</color>
+ <color name="i_am_color_23c1">#000023c1</color>
+ <color name="i_am_color_23c2">#000023c2</color>
+ <color name="i_am_color_23c3">#000023c3</color>
+ <color name="i_am_color_23c4">#000023c4</color>
+ <color name="i_am_color_23c5">#000023c5</color>
+ <color name="i_am_color_23c6">#000023c6</color>
+ <color name="i_am_color_23c7">#000023c7</color>
+ <color name="i_am_color_23c8">#000023c8</color>
+ <color name="i_am_color_23c9">#000023c9</color>
+ <color name="i_am_color_23ca">#000023ca</color>
+ <color name="i_am_color_23cb">#000023cb</color>
+ <color name="i_am_color_23cc">#000023cc</color>
+ <color name="i_am_color_23cd">#000023cd</color>
+ <color name="i_am_color_23ce">#000023ce</color>
+ <color name="i_am_color_23cf">#000023cf</color>
+ <color name="i_am_color_23d0">#000023d0</color>
+ <color name="i_am_color_23d1">#000023d1</color>
+ <color name="i_am_color_23d2">#000023d2</color>
+ <color name="i_am_color_23d3">#000023d3</color>
+ <color name="i_am_color_23d4">#000023d4</color>
+ <color name="i_am_color_23d5">#000023d5</color>
+ <color name="i_am_color_23d6">#000023d6</color>
+ <color name="i_am_color_23d7">#000023d7</color>
+ <color name="i_am_color_23d8">#000023d8</color>
+ <color name="i_am_color_23d9">#000023d9</color>
+ <color name="i_am_color_23da">#000023da</color>
+ <color name="i_am_color_23db">#000023db</color>
+ <color name="i_am_color_23dc">#000023dc</color>
+ <color name="i_am_color_23dd">#000023dd</color>
+ <color name="i_am_color_23de">#000023de</color>
+ <color name="i_am_color_23df">#000023df</color>
+ <color name="i_am_color_23e0">#000023e0</color>
+ <color name="i_am_color_23e1">#000023e1</color>
+ <color name="i_am_color_23e2">#000023e2</color>
+ <color name="i_am_color_23e3">#000023e3</color>
+ <color name="i_am_color_23e4">#000023e4</color>
+ <color name="i_am_color_23e5">#000023e5</color>
+ <color name="i_am_color_23e6">#000023e6</color>
+ <color name="i_am_color_23e7">#000023e7</color>
+ <color name="i_am_color_23e8">#000023e8</color>
+ <color name="i_am_color_23e9">#000023e9</color>
+ <color name="i_am_color_23ea">#000023ea</color>
+ <color name="i_am_color_23eb">#000023eb</color>
+ <color name="i_am_color_23ec">#000023ec</color>
+ <color name="i_am_color_23ed">#000023ed</color>
+ <color name="i_am_color_23ee">#000023ee</color>
+ <color name="i_am_color_23ef">#000023ef</color>
+ <color name="i_am_color_23f0">#000023f0</color>
+ <color name="i_am_color_23f1">#000023f1</color>
+ <color name="i_am_color_23f2">#000023f2</color>
+ <color name="i_am_color_23f3">#000023f3</color>
+ <color name="i_am_color_23f4">#000023f4</color>
+ <color name="i_am_color_23f5">#000023f5</color>
+ <color name="i_am_color_23f6">#000023f6</color>
+ <color name="i_am_color_23f7">#000023f7</color>
+ <color name="i_am_color_23f8">#000023f8</color>
+ <color name="i_am_color_23f9">#000023f9</color>
+ <color name="i_am_color_23fa">#000023fa</color>
+ <color name="i_am_color_23fb">#000023fb</color>
+ <color name="i_am_color_23fc">#000023fc</color>
+ <color name="i_am_color_23fd">#000023fd</color>
+ <color name="i_am_color_23fe">#000023fe</color>
+ <color name="i_am_color_23ff">#000023ff</color>
+ <color name="i_am_color_2400">#00002400</color>
+ <color name="i_am_color_2401">#00002401</color>
+ <color name="i_am_color_2402">#00002402</color>
+ <color name="i_am_color_2403">#00002403</color>
+ <color name="i_am_color_2404">#00002404</color>
+ <color name="i_am_color_2405">#00002405</color>
+ <color name="i_am_color_2406">#00002406</color>
+ <color name="i_am_color_2407">#00002407</color>
+ <color name="i_am_color_2408">#00002408</color>
+ <color name="i_am_color_2409">#00002409</color>
+ <color name="i_am_color_240a">#0000240a</color>
+ <color name="i_am_color_240b">#0000240b</color>
+ <color name="i_am_color_240c">#0000240c</color>
+ <color name="i_am_color_240d">#0000240d</color>
+ <color name="i_am_color_240e">#0000240e</color>
+ <color name="i_am_color_240f">#0000240f</color>
+ <color name="i_am_color_2410">#00002410</color>
+ <color name="i_am_color_2411">#00002411</color>
+ <color name="i_am_color_2412">#00002412</color>
+ <color name="i_am_color_2413">#00002413</color>
+ <color name="i_am_color_2414">#00002414</color>
+ <color name="i_am_color_2415">#00002415</color>
+ <color name="i_am_color_2416">#00002416</color>
+ <color name="i_am_color_2417">#00002417</color>
+ <color name="i_am_color_2418">#00002418</color>
+ <color name="i_am_color_2419">#00002419</color>
+ <color name="i_am_color_241a">#0000241a</color>
+ <color name="i_am_color_241b">#0000241b</color>
+ <color name="i_am_color_241c">#0000241c</color>
+ <color name="i_am_color_241d">#0000241d</color>
+ <color name="i_am_color_241e">#0000241e</color>
+ <color name="i_am_color_241f">#0000241f</color>
+ <color name="i_am_color_2420">#00002420</color>
+ <color name="i_am_color_2421">#00002421</color>
+ <color name="i_am_color_2422">#00002422</color>
+ <color name="i_am_color_2423">#00002423</color>
+ <color name="i_am_color_2424">#00002424</color>
+ <color name="i_am_color_2425">#00002425</color>
+ <color name="i_am_color_2426">#00002426</color>
+ <color name="i_am_color_2427">#00002427</color>
+ <color name="i_am_color_2428">#00002428</color>
+ <color name="i_am_color_2429">#00002429</color>
+ <color name="i_am_color_242a">#0000242a</color>
+ <color name="i_am_color_242b">#0000242b</color>
+ <color name="i_am_color_242c">#0000242c</color>
+ <color name="i_am_color_242d">#0000242d</color>
+ <color name="i_am_color_242e">#0000242e</color>
+ <color name="i_am_color_242f">#0000242f</color>
+ <color name="i_am_color_2430">#00002430</color>
+ <color name="i_am_color_2431">#00002431</color>
+ <color name="i_am_color_2432">#00002432</color>
+ <color name="i_am_color_2433">#00002433</color>
+ <color name="i_am_color_2434">#00002434</color>
+ <color name="i_am_color_2435">#00002435</color>
+ <color name="i_am_color_2436">#00002436</color>
+ <color name="i_am_color_2437">#00002437</color>
+ <color name="i_am_color_2438">#00002438</color>
+ <color name="i_am_color_2439">#00002439</color>
+ <color name="i_am_color_243a">#0000243a</color>
+ <color name="i_am_color_243b">#0000243b</color>
+ <color name="i_am_color_243c">#0000243c</color>
+ <color name="i_am_color_243d">#0000243d</color>
+ <color name="i_am_color_243e">#0000243e</color>
+ <color name="i_am_color_243f">#0000243f</color>
+ <color name="i_am_color_2440">#00002440</color>
+ <color name="i_am_color_2441">#00002441</color>
+ <color name="i_am_color_2442">#00002442</color>
+ <color name="i_am_color_2443">#00002443</color>
+ <color name="i_am_color_2444">#00002444</color>
+ <color name="i_am_color_2445">#00002445</color>
+ <color name="i_am_color_2446">#00002446</color>
+ <color name="i_am_color_2447">#00002447</color>
+ <color name="i_am_color_2448">#00002448</color>
+ <color name="i_am_color_2449">#00002449</color>
+ <color name="i_am_color_244a">#0000244a</color>
+ <color name="i_am_color_244b">#0000244b</color>
+ <color name="i_am_color_244c">#0000244c</color>
+ <color name="i_am_color_244d">#0000244d</color>
+ <color name="i_am_color_244e">#0000244e</color>
+ <color name="i_am_color_244f">#0000244f</color>
+ <color name="i_am_color_2450">#00002450</color>
+ <color name="i_am_color_2451">#00002451</color>
+ <color name="i_am_color_2452">#00002452</color>
+ <color name="i_am_color_2453">#00002453</color>
+ <color name="i_am_color_2454">#00002454</color>
+ <color name="i_am_color_2455">#00002455</color>
+ <color name="i_am_color_2456">#00002456</color>
+ <color name="i_am_color_2457">#00002457</color>
+ <color name="i_am_color_2458">#00002458</color>
+ <color name="i_am_color_2459">#00002459</color>
+ <color name="i_am_color_245a">#0000245a</color>
+ <color name="i_am_color_245b">#0000245b</color>
+ <color name="i_am_color_245c">#0000245c</color>
+ <color name="i_am_color_245d">#0000245d</color>
+ <color name="i_am_color_245e">#0000245e</color>
+ <color name="i_am_color_245f">#0000245f</color>
+ <color name="i_am_color_2460">#00002460</color>
+ <color name="i_am_color_2461">#00002461</color>
+ <color name="i_am_color_2462">#00002462</color>
+ <color name="i_am_color_2463">#00002463</color>
+ <color name="i_am_color_2464">#00002464</color>
+ <color name="i_am_color_2465">#00002465</color>
+ <color name="i_am_color_2466">#00002466</color>
+ <color name="i_am_color_2467">#00002467</color>
+ <color name="i_am_color_2468">#00002468</color>
+ <color name="i_am_color_2469">#00002469</color>
+ <color name="i_am_color_246a">#0000246a</color>
+ <color name="i_am_color_246b">#0000246b</color>
+ <color name="i_am_color_246c">#0000246c</color>
+ <color name="i_am_color_246d">#0000246d</color>
+ <color name="i_am_color_246e">#0000246e</color>
+ <color name="i_am_color_246f">#0000246f</color>
+ <color name="i_am_color_2470">#00002470</color>
+ <color name="i_am_color_2471">#00002471</color>
+ <color name="i_am_color_2472">#00002472</color>
+ <color name="i_am_color_2473">#00002473</color>
+ <color name="i_am_color_2474">#00002474</color>
+ <color name="i_am_color_2475">#00002475</color>
+ <color name="i_am_color_2476">#00002476</color>
+ <color name="i_am_color_2477">#00002477</color>
+ <color name="i_am_color_2478">#00002478</color>
+ <color name="i_am_color_2479">#00002479</color>
+ <color name="i_am_color_247a">#0000247a</color>
+ <color name="i_am_color_247b">#0000247b</color>
+ <color name="i_am_color_247c">#0000247c</color>
+ <color name="i_am_color_247d">#0000247d</color>
+ <color name="i_am_color_247e">#0000247e</color>
+ <color name="i_am_color_247f">#0000247f</color>
+ <color name="i_am_color_2480">#00002480</color>
+ <color name="i_am_color_2481">#00002481</color>
+ <color name="i_am_color_2482">#00002482</color>
+ <color name="i_am_color_2483">#00002483</color>
+ <color name="i_am_color_2484">#00002484</color>
+ <color name="i_am_color_2485">#00002485</color>
+ <color name="i_am_color_2486">#00002486</color>
+ <color name="i_am_color_2487">#00002487</color>
+ <color name="i_am_color_2488">#00002488</color>
+ <color name="i_am_color_2489">#00002489</color>
+ <color name="i_am_color_248a">#0000248a</color>
+ <color name="i_am_color_248b">#0000248b</color>
+ <color name="i_am_color_248c">#0000248c</color>
+ <color name="i_am_color_248d">#0000248d</color>
+ <color name="i_am_color_248e">#0000248e</color>
+ <color name="i_am_color_248f">#0000248f</color>
+ <color name="i_am_color_2490">#00002490</color>
+ <color name="i_am_color_2491">#00002491</color>
+ <color name="i_am_color_2492">#00002492</color>
+ <color name="i_am_color_2493">#00002493</color>
+ <color name="i_am_color_2494">#00002494</color>
+ <color name="i_am_color_2495">#00002495</color>
+ <color name="i_am_color_2496">#00002496</color>
+ <color name="i_am_color_2497">#00002497</color>
+ <color name="i_am_color_2498">#00002498</color>
+ <color name="i_am_color_2499">#00002499</color>
+ <color name="i_am_color_249a">#0000249a</color>
+ <color name="i_am_color_249b">#0000249b</color>
+ <color name="i_am_color_249c">#0000249c</color>
+ <color name="i_am_color_249d">#0000249d</color>
+ <color name="i_am_color_249e">#0000249e</color>
+ <color name="i_am_color_249f">#0000249f</color>
+ <color name="i_am_color_24a0">#000024a0</color>
+ <color name="i_am_color_24a1">#000024a1</color>
+ <color name="i_am_color_24a2">#000024a2</color>
+ <color name="i_am_color_24a3">#000024a3</color>
+ <color name="i_am_color_24a4">#000024a4</color>
+ <color name="i_am_color_24a5">#000024a5</color>
+ <color name="i_am_color_24a6">#000024a6</color>
+ <color name="i_am_color_24a7">#000024a7</color>
+ <color name="i_am_color_24a8">#000024a8</color>
+ <color name="i_am_color_24a9">#000024a9</color>
+ <color name="i_am_color_24aa">#000024aa</color>
+ <color name="i_am_color_24ab">#000024ab</color>
+ <color name="i_am_color_24ac">#000024ac</color>
+ <color name="i_am_color_24ad">#000024ad</color>
+ <color name="i_am_color_24ae">#000024ae</color>
+ <color name="i_am_color_24af">#000024af</color>
+ <color name="i_am_color_24b0">#000024b0</color>
+ <color name="i_am_color_24b1">#000024b1</color>
+ <color name="i_am_color_24b2">#000024b2</color>
+ <color name="i_am_color_24b3">#000024b3</color>
+ <color name="i_am_color_24b4">#000024b4</color>
+ <color name="i_am_color_24b5">#000024b5</color>
+ <color name="i_am_color_24b6">#000024b6</color>
+ <color name="i_am_color_24b7">#000024b7</color>
+ <color name="i_am_color_24b8">#000024b8</color>
+ <color name="i_am_color_24b9">#000024b9</color>
+ <color name="i_am_color_24ba">#000024ba</color>
+ <color name="i_am_color_24bb">#000024bb</color>
+ <color name="i_am_color_24bc">#000024bc</color>
+ <color name="i_am_color_24bd">#000024bd</color>
+ <color name="i_am_color_24be">#000024be</color>
+ <color name="i_am_color_24bf">#000024bf</color>
+ <color name="i_am_color_24c0">#000024c0</color>
+ <color name="i_am_color_24c1">#000024c1</color>
+ <color name="i_am_color_24c2">#000024c2</color>
+ <color name="i_am_color_24c3">#000024c3</color>
+ <color name="i_am_color_24c4">#000024c4</color>
+ <color name="i_am_color_24c5">#000024c5</color>
+ <color name="i_am_color_24c6">#000024c6</color>
+ <color name="i_am_color_24c7">#000024c7</color>
+ <color name="i_am_color_24c8">#000024c8</color>
+ <color name="i_am_color_24c9">#000024c9</color>
+ <color name="i_am_color_24ca">#000024ca</color>
+ <color name="i_am_color_24cb">#000024cb</color>
+ <color name="i_am_color_24cc">#000024cc</color>
+ <color name="i_am_color_24cd">#000024cd</color>
+ <color name="i_am_color_24ce">#000024ce</color>
+ <color name="i_am_color_24cf">#000024cf</color>
+ <color name="i_am_color_24d0">#000024d0</color>
+ <color name="i_am_color_24d1">#000024d1</color>
+ <color name="i_am_color_24d2">#000024d2</color>
+ <color name="i_am_color_24d3">#000024d3</color>
+ <color name="i_am_color_24d4">#000024d4</color>
+ <color name="i_am_color_24d5">#000024d5</color>
+ <color name="i_am_color_24d6">#000024d6</color>
+ <color name="i_am_color_24d7">#000024d7</color>
+ <color name="i_am_color_24d8">#000024d8</color>
+ <color name="i_am_color_24d9">#000024d9</color>
+ <color name="i_am_color_24da">#000024da</color>
+ <color name="i_am_color_24db">#000024db</color>
+ <color name="i_am_color_24dc">#000024dc</color>
+ <color name="i_am_color_24dd">#000024dd</color>
+ <color name="i_am_color_24de">#000024de</color>
+ <color name="i_am_color_24df">#000024df</color>
+ <color name="i_am_color_24e0">#000024e0</color>
+ <color name="i_am_color_24e1">#000024e1</color>
+ <color name="i_am_color_24e2">#000024e2</color>
+ <color name="i_am_color_24e3">#000024e3</color>
+ <color name="i_am_color_24e4">#000024e4</color>
+ <color name="i_am_color_24e5">#000024e5</color>
+ <color name="i_am_color_24e6">#000024e6</color>
+ <color name="i_am_color_24e7">#000024e7</color>
+ <color name="i_am_color_24e8">#000024e8</color>
+ <color name="i_am_color_24e9">#000024e9</color>
+ <color name="i_am_color_24ea">#000024ea</color>
+ <color name="i_am_color_24eb">#000024eb</color>
+ <color name="i_am_color_24ec">#000024ec</color>
+ <color name="i_am_color_24ed">#000024ed</color>
+ <color name="i_am_color_24ee">#000024ee</color>
+ <color name="i_am_color_24ef">#000024ef</color>
+ <color name="i_am_color_24f0">#000024f0</color>
+ <color name="i_am_color_24f1">#000024f1</color>
+ <color name="i_am_color_24f2">#000024f2</color>
+ <color name="i_am_color_24f3">#000024f3</color>
+ <color name="i_am_color_24f4">#000024f4</color>
+ <color name="i_am_color_24f5">#000024f5</color>
+ <color name="i_am_color_24f6">#000024f6</color>
+ <color name="i_am_color_24f7">#000024f7</color>
+ <color name="i_am_color_24f8">#000024f8</color>
+ <color name="i_am_color_24f9">#000024f9</color>
+ <color name="i_am_color_24fa">#000024fa</color>
+ <color name="i_am_color_24fb">#000024fb</color>
+ <color name="i_am_color_24fc">#000024fc</color>
+ <color name="i_am_color_24fd">#000024fd</color>
+ <color name="i_am_color_24fe">#000024fe</color>
+ <color name="i_am_color_24ff">#000024ff</color>
+ <color name="i_am_color_2500">#00002500</color>
+ <color name="i_am_color_2501">#00002501</color>
+ <color name="i_am_color_2502">#00002502</color>
+ <color name="i_am_color_2503">#00002503</color>
+ <color name="i_am_color_2504">#00002504</color>
+ <color name="i_am_color_2505">#00002505</color>
+ <color name="i_am_color_2506">#00002506</color>
+ <color name="i_am_color_2507">#00002507</color>
+ <color name="i_am_color_2508">#00002508</color>
+ <color name="i_am_color_2509">#00002509</color>
+ <color name="i_am_color_250a">#0000250a</color>
+ <color name="i_am_color_250b">#0000250b</color>
+ <color name="i_am_color_250c">#0000250c</color>
+ <color name="i_am_color_250d">#0000250d</color>
+ <color name="i_am_color_250e">#0000250e</color>
+ <color name="i_am_color_250f">#0000250f</color>
+ <color name="i_am_color_2510">#00002510</color>
+ <color name="i_am_color_2511">#00002511</color>
+ <color name="i_am_color_2512">#00002512</color>
+ <color name="i_am_color_2513">#00002513</color>
+ <color name="i_am_color_2514">#00002514</color>
+ <color name="i_am_color_2515">#00002515</color>
+ <color name="i_am_color_2516">#00002516</color>
+ <color name="i_am_color_2517">#00002517</color>
+ <color name="i_am_color_2518">#00002518</color>
+ <color name="i_am_color_2519">#00002519</color>
+ <color name="i_am_color_251a">#0000251a</color>
+ <color name="i_am_color_251b">#0000251b</color>
+ <color name="i_am_color_251c">#0000251c</color>
+ <color name="i_am_color_251d">#0000251d</color>
+ <color name="i_am_color_251e">#0000251e</color>
+ <color name="i_am_color_251f">#0000251f</color>
+ <color name="i_am_color_2520">#00002520</color>
+ <color name="i_am_color_2521">#00002521</color>
+ <color name="i_am_color_2522">#00002522</color>
+ <color name="i_am_color_2523">#00002523</color>
+ <color name="i_am_color_2524">#00002524</color>
+ <color name="i_am_color_2525">#00002525</color>
+ <color name="i_am_color_2526">#00002526</color>
+ <color name="i_am_color_2527">#00002527</color>
+ <color name="i_am_color_2528">#00002528</color>
+ <color name="i_am_color_2529">#00002529</color>
+ <color name="i_am_color_252a">#0000252a</color>
+ <color name="i_am_color_252b">#0000252b</color>
+ <color name="i_am_color_252c">#0000252c</color>
+ <color name="i_am_color_252d">#0000252d</color>
+ <color name="i_am_color_252e">#0000252e</color>
+ <color name="i_am_color_252f">#0000252f</color>
+ <color name="i_am_color_2530">#00002530</color>
+ <color name="i_am_color_2531">#00002531</color>
+ <color name="i_am_color_2532">#00002532</color>
+ <color name="i_am_color_2533">#00002533</color>
+ <color name="i_am_color_2534">#00002534</color>
+ <color name="i_am_color_2535">#00002535</color>
+ <color name="i_am_color_2536">#00002536</color>
+ <color name="i_am_color_2537">#00002537</color>
+ <color name="i_am_color_2538">#00002538</color>
+ <color name="i_am_color_2539">#00002539</color>
+ <color name="i_am_color_253a">#0000253a</color>
+ <color name="i_am_color_253b">#0000253b</color>
+ <color name="i_am_color_253c">#0000253c</color>
+ <color name="i_am_color_253d">#0000253d</color>
+ <color name="i_am_color_253e">#0000253e</color>
+ <color name="i_am_color_253f">#0000253f</color>
+ <color name="i_am_color_2540">#00002540</color>
+ <color name="i_am_color_2541">#00002541</color>
+ <color name="i_am_color_2542">#00002542</color>
+ <color name="i_am_color_2543">#00002543</color>
+ <color name="i_am_color_2544">#00002544</color>
+ <color name="i_am_color_2545">#00002545</color>
+ <color name="i_am_color_2546">#00002546</color>
+ <color name="i_am_color_2547">#00002547</color>
+ <color name="i_am_color_2548">#00002548</color>
+ <color name="i_am_color_2549">#00002549</color>
+ <color name="i_am_color_254a">#0000254a</color>
+ <color name="i_am_color_254b">#0000254b</color>
+ <color name="i_am_color_254c">#0000254c</color>
+ <color name="i_am_color_254d">#0000254d</color>
+ <color name="i_am_color_254e">#0000254e</color>
+ <color name="i_am_color_254f">#0000254f</color>
+ <color name="i_am_color_2550">#00002550</color>
+ <color name="i_am_color_2551">#00002551</color>
+ <color name="i_am_color_2552">#00002552</color>
+ <color name="i_am_color_2553">#00002553</color>
+ <color name="i_am_color_2554">#00002554</color>
+ <color name="i_am_color_2555">#00002555</color>
+ <color name="i_am_color_2556">#00002556</color>
+ <color name="i_am_color_2557">#00002557</color>
+ <color name="i_am_color_2558">#00002558</color>
+ <color name="i_am_color_2559">#00002559</color>
+ <color name="i_am_color_255a">#0000255a</color>
+ <color name="i_am_color_255b">#0000255b</color>
+ <color name="i_am_color_255c">#0000255c</color>
+ <color name="i_am_color_255d">#0000255d</color>
+ <color name="i_am_color_255e">#0000255e</color>
+ <color name="i_am_color_255f">#0000255f</color>
+ <color name="i_am_color_2560">#00002560</color>
+ <color name="i_am_color_2561">#00002561</color>
+ <color name="i_am_color_2562">#00002562</color>
+ <color name="i_am_color_2563">#00002563</color>
+ <color name="i_am_color_2564">#00002564</color>
+ <color name="i_am_color_2565">#00002565</color>
+ <color name="i_am_color_2566">#00002566</color>
+ <color name="i_am_color_2567">#00002567</color>
+ <color name="i_am_color_2568">#00002568</color>
+ <color name="i_am_color_2569">#00002569</color>
+ <color name="i_am_color_256a">#0000256a</color>
+ <color name="i_am_color_256b">#0000256b</color>
+ <color name="i_am_color_256c">#0000256c</color>
+ <color name="i_am_color_256d">#0000256d</color>
+ <color name="i_am_color_256e">#0000256e</color>
+ <color name="i_am_color_256f">#0000256f</color>
+ <color name="i_am_color_2570">#00002570</color>
+ <color name="i_am_color_2571">#00002571</color>
+ <color name="i_am_color_2572">#00002572</color>
+ <color name="i_am_color_2573">#00002573</color>
+ <color name="i_am_color_2574">#00002574</color>
+ <color name="i_am_color_2575">#00002575</color>
+ <color name="i_am_color_2576">#00002576</color>
+ <color name="i_am_color_2577">#00002577</color>
+ <color name="i_am_color_2578">#00002578</color>
+ <color name="i_am_color_2579">#00002579</color>
+ <color name="i_am_color_257a">#0000257a</color>
+ <color name="i_am_color_257b">#0000257b</color>
+ <color name="i_am_color_257c">#0000257c</color>
+ <color name="i_am_color_257d">#0000257d</color>
+ <color name="i_am_color_257e">#0000257e</color>
+ <color name="i_am_color_257f">#0000257f</color>
+ <color name="i_am_color_2580">#00002580</color>
+ <color name="i_am_color_2581">#00002581</color>
+ <color name="i_am_color_2582">#00002582</color>
+ <color name="i_am_color_2583">#00002583</color>
+ <color name="i_am_color_2584">#00002584</color>
+ <color name="i_am_color_2585">#00002585</color>
+ <color name="i_am_color_2586">#00002586</color>
+ <color name="i_am_color_2587">#00002587</color>
+ <color name="i_am_color_2588">#00002588</color>
+ <color name="i_am_color_2589">#00002589</color>
+ <color name="i_am_color_258a">#0000258a</color>
+ <color name="i_am_color_258b">#0000258b</color>
+ <color name="i_am_color_258c">#0000258c</color>
+ <color name="i_am_color_258d">#0000258d</color>
+ <color name="i_am_color_258e">#0000258e</color>
+ <color name="i_am_color_258f">#0000258f</color>
+ <color name="i_am_color_2590">#00002590</color>
+ <color name="i_am_color_2591">#00002591</color>
+ <color name="i_am_color_2592">#00002592</color>
+ <color name="i_am_color_2593">#00002593</color>
+ <color name="i_am_color_2594">#00002594</color>
+ <color name="i_am_color_2595">#00002595</color>
+ <color name="i_am_color_2596">#00002596</color>
+ <color name="i_am_color_2597">#00002597</color>
+ <color name="i_am_color_2598">#00002598</color>
+ <color name="i_am_color_2599">#00002599</color>
+ <color name="i_am_color_259a">#0000259a</color>
+ <color name="i_am_color_259b">#0000259b</color>
+ <color name="i_am_color_259c">#0000259c</color>
+ <color name="i_am_color_259d">#0000259d</color>
+ <color name="i_am_color_259e">#0000259e</color>
+ <color name="i_am_color_259f">#0000259f</color>
+ <color name="i_am_color_25a0">#000025a0</color>
+ <color name="i_am_color_25a1">#000025a1</color>
+ <color name="i_am_color_25a2">#000025a2</color>
+ <color name="i_am_color_25a3">#000025a3</color>
+ <color name="i_am_color_25a4">#000025a4</color>
+ <color name="i_am_color_25a5">#000025a5</color>
+ <color name="i_am_color_25a6">#000025a6</color>
+ <color name="i_am_color_25a7">#000025a7</color>
+ <color name="i_am_color_25a8">#000025a8</color>
+ <color name="i_am_color_25a9">#000025a9</color>
+ <color name="i_am_color_25aa">#000025aa</color>
+ <color name="i_am_color_25ab">#000025ab</color>
+ <color name="i_am_color_25ac">#000025ac</color>
+ <color name="i_am_color_25ad">#000025ad</color>
+ <color name="i_am_color_25ae">#000025ae</color>
+ <color name="i_am_color_25af">#000025af</color>
+ <color name="i_am_color_25b0">#000025b0</color>
+ <color name="i_am_color_25b1">#000025b1</color>
+ <color name="i_am_color_25b2">#000025b2</color>
+ <color name="i_am_color_25b3">#000025b3</color>
+ <color name="i_am_color_25b4">#000025b4</color>
+ <color name="i_am_color_25b5">#000025b5</color>
+ <color name="i_am_color_25b6">#000025b6</color>
+ <color name="i_am_color_25b7">#000025b7</color>
+ <color name="i_am_color_25b8">#000025b8</color>
+ <color name="i_am_color_25b9">#000025b9</color>
+ <color name="i_am_color_25ba">#000025ba</color>
+ <color name="i_am_color_25bb">#000025bb</color>
+ <color name="i_am_color_25bc">#000025bc</color>
+ <color name="i_am_color_25bd">#000025bd</color>
+ <color name="i_am_color_25be">#000025be</color>
+ <color name="i_am_color_25bf">#000025bf</color>
+ <color name="i_am_color_25c0">#000025c0</color>
+ <color name="i_am_color_25c1">#000025c1</color>
+ <color name="i_am_color_25c2">#000025c2</color>
+ <color name="i_am_color_25c3">#000025c3</color>
+ <color name="i_am_color_25c4">#000025c4</color>
+ <color name="i_am_color_25c5">#000025c5</color>
+ <color name="i_am_color_25c6">#000025c6</color>
+ <color name="i_am_color_25c7">#000025c7</color>
+ <color name="i_am_color_25c8">#000025c8</color>
+ <color name="i_am_color_25c9">#000025c9</color>
+ <color name="i_am_color_25ca">#000025ca</color>
+ <color name="i_am_color_25cb">#000025cb</color>
+ <color name="i_am_color_25cc">#000025cc</color>
+ <color name="i_am_color_25cd">#000025cd</color>
+ <color name="i_am_color_25ce">#000025ce</color>
+ <color name="i_am_color_25cf">#000025cf</color>
+ <color name="i_am_color_25d0">#000025d0</color>
+ <color name="i_am_color_25d1">#000025d1</color>
+ <color name="i_am_color_25d2">#000025d2</color>
+ <color name="i_am_color_25d3">#000025d3</color>
+ <color name="i_am_color_25d4">#000025d4</color>
+ <color name="i_am_color_25d5">#000025d5</color>
+ <color name="i_am_color_25d6">#000025d6</color>
+ <color name="i_am_color_25d7">#000025d7</color>
+ <color name="i_am_color_25d8">#000025d8</color>
+ <color name="i_am_color_25d9">#000025d9</color>
+ <color name="i_am_color_25da">#000025da</color>
+ <color name="i_am_color_25db">#000025db</color>
+ <color name="i_am_color_25dc">#000025dc</color>
+ <color name="i_am_color_25dd">#000025dd</color>
+ <color name="i_am_color_25de">#000025de</color>
+ <color name="i_am_color_25df">#000025df</color>
+ <color name="i_am_color_25e0">#000025e0</color>
+ <color name="i_am_color_25e1">#000025e1</color>
+ <color name="i_am_color_25e2">#000025e2</color>
+ <color name="i_am_color_25e3">#000025e3</color>
+ <color name="i_am_color_25e4">#000025e4</color>
+ <color name="i_am_color_25e5">#000025e5</color>
+ <color name="i_am_color_25e6">#000025e6</color>
+ <color name="i_am_color_25e7">#000025e7</color>
+ <color name="i_am_color_25e8">#000025e8</color>
+ <color name="i_am_color_25e9">#000025e9</color>
+ <color name="i_am_color_25ea">#000025ea</color>
+ <color name="i_am_color_25eb">#000025eb</color>
+ <color name="i_am_color_25ec">#000025ec</color>
+ <color name="i_am_color_25ed">#000025ed</color>
+ <color name="i_am_color_25ee">#000025ee</color>
+ <color name="i_am_color_25ef">#000025ef</color>
+ <color name="i_am_color_25f0">#000025f0</color>
+ <color name="i_am_color_25f1">#000025f1</color>
+ <color name="i_am_color_25f2">#000025f2</color>
+ <color name="i_am_color_25f3">#000025f3</color>
+ <color name="i_am_color_25f4">#000025f4</color>
+ <color name="i_am_color_25f5">#000025f5</color>
+ <color name="i_am_color_25f6">#000025f6</color>
+ <color name="i_am_color_25f7">#000025f7</color>
+ <color name="i_am_color_25f8">#000025f8</color>
+ <color name="i_am_color_25f9">#000025f9</color>
+ <color name="i_am_color_25fa">#000025fa</color>
+ <color name="i_am_color_25fb">#000025fb</color>
+ <color name="i_am_color_25fc">#000025fc</color>
+ <color name="i_am_color_25fd">#000025fd</color>
+ <color name="i_am_color_25fe">#000025fe</color>
+ <color name="i_am_color_25ff">#000025ff</color>
+ <color name="i_am_color_2600">#00002600</color>
+ <color name="i_am_color_2601">#00002601</color>
+ <color name="i_am_color_2602">#00002602</color>
+ <color name="i_am_color_2603">#00002603</color>
+ <color name="i_am_color_2604">#00002604</color>
+ <color name="i_am_color_2605">#00002605</color>
+ <color name="i_am_color_2606">#00002606</color>
+ <color name="i_am_color_2607">#00002607</color>
+ <color name="i_am_color_2608">#00002608</color>
+ <color name="i_am_color_2609">#00002609</color>
+ <color name="i_am_color_260a">#0000260a</color>
+ <color name="i_am_color_260b">#0000260b</color>
+ <color name="i_am_color_260c">#0000260c</color>
+ <color name="i_am_color_260d">#0000260d</color>
+ <color name="i_am_color_260e">#0000260e</color>
+ <color name="i_am_color_260f">#0000260f</color>
+ <color name="i_am_color_2610">#00002610</color>
+ <color name="i_am_color_2611">#00002611</color>
+ <color name="i_am_color_2612">#00002612</color>
+ <color name="i_am_color_2613">#00002613</color>
+ <color name="i_am_color_2614">#00002614</color>
+ <color name="i_am_color_2615">#00002615</color>
+ <color name="i_am_color_2616">#00002616</color>
+ <color name="i_am_color_2617">#00002617</color>
+ <color name="i_am_color_2618">#00002618</color>
+ <color name="i_am_color_2619">#00002619</color>
+ <color name="i_am_color_261a">#0000261a</color>
+ <color name="i_am_color_261b">#0000261b</color>
+ <color name="i_am_color_261c">#0000261c</color>
+ <color name="i_am_color_261d">#0000261d</color>
+ <color name="i_am_color_261e">#0000261e</color>
+ <color name="i_am_color_261f">#0000261f</color>
+ <color name="i_am_color_2620">#00002620</color>
+ <color name="i_am_color_2621">#00002621</color>
+ <color name="i_am_color_2622">#00002622</color>
+ <color name="i_am_color_2623">#00002623</color>
+ <color name="i_am_color_2624">#00002624</color>
+ <color name="i_am_color_2625">#00002625</color>
+ <color name="i_am_color_2626">#00002626</color>
+ <color name="i_am_color_2627">#00002627</color>
+ <color name="i_am_color_2628">#00002628</color>
+ <color name="i_am_color_2629">#00002629</color>
+ <color name="i_am_color_262a">#0000262a</color>
+ <color name="i_am_color_262b">#0000262b</color>
+ <color name="i_am_color_262c">#0000262c</color>
+ <color name="i_am_color_262d">#0000262d</color>
+ <color name="i_am_color_262e">#0000262e</color>
+ <color name="i_am_color_262f">#0000262f</color>
+ <color name="i_am_color_2630">#00002630</color>
+ <color name="i_am_color_2631">#00002631</color>
+ <color name="i_am_color_2632">#00002632</color>
+ <color name="i_am_color_2633">#00002633</color>
+ <color name="i_am_color_2634">#00002634</color>
+ <color name="i_am_color_2635">#00002635</color>
+ <color name="i_am_color_2636">#00002636</color>
+ <color name="i_am_color_2637">#00002637</color>
+ <color name="i_am_color_2638">#00002638</color>
+ <color name="i_am_color_2639">#00002639</color>
+ <color name="i_am_color_263a">#0000263a</color>
+ <color name="i_am_color_263b">#0000263b</color>
+ <color name="i_am_color_263c">#0000263c</color>
+ <color name="i_am_color_263d">#0000263d</color>
+ <color name="i_am_color_263e">#0000263e</color>
+ <color name="i_am_color_263f">#0000263f</color>
+ <color name="i_am_color_2640">#00002640</color>
+ <color name="i_am_color_2641">#00002641</color>
+ <color name="i_am_color_2642">#00002642</color>
+ <color name="i_am_color_2643">#00002643</color>
+ <color name="i_am_color_2644">#00002644</color>
+ <color name="i_am_color_2645">#00002645</color>
+ <color name="i_am_color_2646">#00002646</color>
+ <color name="i_am_color_2647">#00002647</color>
+ <color name="i_am_color_2648">#00002648</color>
+ <color name="i_am_color_2649">#00002649</color>
+ <color name="i_am_color_264a">#0000264a</color>
+ <color name="i_am_color_264b">#0000264b</color>
+ <color name="i_am_color_264c">#0000264c</color>
+ <color name="i_am_color_264d">#0000264d</color>
+ <color name="i_am_color_264e">#0000264e</color>
+ <color name="i_am_color_264f">#0000264f</color>
+ <color name="i_am_color_2650">#00002650</color>
+ <color name="i_am_color_2651">#00002651</color>
+ <color name="i_am_color_2652">#00002652</color>
+ <color name="i_am_color_2653">#00002653</color>
+ <color name="i_am_color_2654">#00002654</color>
+ <color name="i_am_color_2655">#00002655</color>
+ <color name="i_am_color_2656">#00002656</color>
+ <color name="i_am_color_2657">#00002657</color>
+ <color name="i_am_color_2658">#00002658</color>
+ <color name="i_am_color_2659">#00002659</color>
+ <color name="i_am_color_265a">#0000265a</color>
+ <color name="i_am_color_265b">#0000265b</color>
+ <color name="i_am_color_265c">#0000265c</color>
+ <color name="i_am_color_265d">#0000265d</color>
+ <color name="i_am_color_265e">#0000265e</color>
+ <color name="i_am_color_265f">#0000265f</color>
+ <color name="i_am_color_2660">#00002660</color>
+ <color name="i_am_color_2661">#00002661</color>
+ <color name="i_am_color_2662">#00002662</color>
+ <color name="i_am_color_2663">#00002663</color>
+ <color name="i_am_color_2664">#00002664</color>
+ <color name="i_am_color_2665">#00002665</color>
+ <color name="i_am_color_2666">#00002666</color>
+ <color name="i_am_color_2667">#00002667</color>
+ <color name="i_am_color_2668">#00002668</color>
+ <color name="i_am_color_2669">#00002669</color>
+ <color name="i_am_color_266a">#0000266a</color>
+ <color name="i_am_color_266b">#0000266b</color>
+ <color name="i_am_color_266c">#0000266c</color>
+ <color name="i_am_color_266d">#0000266d</color>
+ <color name="i_am_color_266e">#0000266e</color>
+ <color name="i_am_color_266f">#0000266f</color>
+ <color name="i_am_color_2670">#00002670</color>
+ <color name="i_am_color_2671">#00002671</color>
+ <color name="i_am_color_2672">#00002672</color>
+ <color name="i_am_color_2673">#00002673</color>
+ <color name="i_am_color_2674">#00002674</color>
+ <color name="i_am_color_2675">#00002675</color>
+ <color name="i_am_color_2676">#00002676</color>
+ <color name="i_am_color_2677">#00002677</color>
+ <color name="i_am_color_2678">#00002678</color>
+ <color name="i_am_color_2679">#00002679</color>
+ <color name="i_am_color_267a">#0000267a</color>
+ <color name="i_am_color_267b">#0000267b</color>
+ <color name="i_am_color_267c">#0000267c</color>
+ <color name="i_am_color_267d">#0000267d</color>
+ <color name="i_am_color_267e">#0000267e</color>
+ <color name="i_am_color_267f">#0000267f</color>
+ <color name="i_am_color_2680">#00002680</color>
+ <color name="i_am_color_2681">#00002681</color>
+ <color name="i_am_color_2682">#00002682</color>
+ <color name="i_am_color_2683">#00002683</color>
+ <color name="i_am_color_2684">#00002684</color>
+ <color name="i_am_color_2685">#00002685</color>
+ <color name="i_am_color_2686">#00002686</color>
+ <color name="i_am_color_2687">#00002687</color>
+ <color name="i_am_color_2688">#00002688</color>
+ <color name="i_am_color_2689">#00002689</color>
+ <color name="i_am_color_268a">#0000268a</color>
+ <color name="i_am_color_268b">#0000268b</color>
+ <color name="i_am_color_268c">#0000268c</color>
+ <color name="i_am_color_268d">#0000268d</color>
+ <color name="i_am_color_268e">#0000268e</color>
+ <color name="i_am_color_268f">#0000268f</color>
+ <color name="i_am_color_2690">#00002690</color>
+ <color name="i_am_color_2691">#00002691</color>
+ <color name="i_am_color_2692">#00002692</color>
+ <color name="i_am_color_2693">#00002693</color>
+ <color name="i_am_color_2694">#00002694</color>
+ <color name="i_am_color_2695">#00002695</color>
+ <color name="i_am_color_2696">#00002696</color>
+ <color name="i_am_color_2697">#00002697</color>
+ <color name="i_am_color_2698">#00002698</color>
+ <color name="i_am_color_2699">#00002699</color>
+ <color name="i_am_color_269a">#0000269a</color>
+ <color name="i_am_color_269b">#0000269b</color>
+ <color name="i_am_color_269c">#0000269c</color>
+ <color name="i_am_color_269d">#0000269d</color>
+ <color name="i_am_color_269e">#0000269e</color>
+ <color name="i_am_color_269f">#0000269f</color>
+ <color name="i_am_color_26a0">#000026a0</color>
+ <color name="i_am_color_26a1">#000026a1</color>
+ <color name="i_am_color_26a2">#000026a2</color>
+ <color name="i_am_color_26a3">#000026a3</color>
+ <color name="i_am_color_26a4">#000026a4</color>
+ <color name="i_am_color_26a5">#000026a5</color>
+ <color name="i_am_color_26a6">#000026a6</color>
+ <color name="i_am_color_26a7">#000026a7</color>
+ <color name="i_am_color_26a8">#000026a8</color>
+ <color name="i_am_color_26a9">#000026a9</color>
+ <color name="i_am_color_26aa">#000026aa</color>
+ <color name="i_am_color_26ab">#000026ab</color>
+ <color name="i_am_color_26ac">#000026ac</color>
+ <color name="i_am_color_26ad">#000026ad</color>
+ <color name="i_am_color_26ae">#000026ae</color>
+ <color name="i_am_color_26af">#000026af</color>
+ <color name="i_am_color_26b0">#000026b0</color>
+ <color name="i_am_color_26b1">#000026b1</color>
+ <color name="i_am_color_26b2">#000026b2</color>
+ <color name="i_am_color_26b3">#000026b3</color>
+ <color name="i_am_color_26b4">#000026b4</color>
+ <color name="i_am_color_26b5">#000026b5</color>
+ <color name="i_am_color_26b6">#000026b6</color>
+ <color name="i_am_color_26b7">#000026b7</color>
+ <color name="i_am_color_26b8">#000026b8</color>
+ <color name="i_am_color_26b9">#000026b9</color>
+ <color name="i_am_color_26ba">#000026ba</color>
+ <color name="i_am_color_26bb">#000026bb</color>
+ <color name="i_am_color_26bc">#000026bc</color>
+ <color name="i_am_color_26bd">#000026bd</color>
+ <color name="i_am_color_26be">#000026be</color>
+ <color name="i_am_color_26bf">#000026bf</color>
+ <color name="i_am_color_26c0">#000026c0</color>
+ <color name="i_am_color_26c1">#000026c1</color>
+ <color name="i_am_color_26c2">#000026c2</color>
+ <color name="i_am_color_26c3">#000026c3</color>
+ <color name="i_am_color_26c4">#000026c4</color>
+ <color name="i_am_color_26c5">#000026c5</color>
+ <color name="i_am_color_26c6">#000026c6</color>
+ <color name="i_am_color_26c7">#000026c7</color>
+ <color name="i_am_color_26c8">#000026c8</color>
+ <color name="i_am_color_26c9">#000026c9</color>
+ <color name="i_am_color_26ca">#000026ca</color>
+ <color name="i_am_color_26cb">#000026cb</color>
+ <color name="i_am_color_26cc">#000026cc</color>
+ <color name="i_am_color_26cd">#000026cd</color>
+ <color name="i_am_color_26ce">#000026ce</color>
+ <color name="i_am_color_26cf">#000026cf</color>
+ <color name="i_am_color_26d0">#000026d0</color>
+ <color name="i_am_color_26d1">#000026d1</color>
+ <color name="i_am_color_26d2">#000026d2</color>
+ <color name="i_am_color_26d3">#000026d3</color>
+ <color name="i_am_color_26d4">#000026d4</color>
+ <color name="i_am_color_26d5">#000026d5</color>
+ <color name="i_am_color_26d6">#000026d6</color>
+ <color name="i_am_color_26d7">#000026d7</color>
+ <color name="i_am_color_26d8">#000026d8</color>
+ <color name="i_am_color_26d9">#000026d9</color>
+ <color name="i_am_color_26da">#000026da</color>
+ <color name="i_am_color_26db">#000026db</color>
+ <color name="i_am_color_26dc">#000026dc</color>
+ <color name="i_am_color_26dd">#000026dd</color>
+ <color name="i_am_color_26de">#000026de</color>
+ <color name="i_am_color_26df">#000026df</color>
+ <color name="i_am_color_26e0">#000026e0</color>
+ <color name="i_am_color_26e1">#000026e1</color>
+ <color name="i_am_color_26e2">#000026e2</color>
+ <color name="i_am_color_26e3">#000026e3</color>
+ <color name="i_am_color_26e4">#000026e4</color>
+ <color name="i_am_color_26e5">#000026e5</color>
+ <color name="i_am_color_26e6">#000026e6</color>
+ <color name="i_am_color_26e7">#000026e7</color>
+ <color name="i_am_color_26e8">#000026e8</color>
+ <color name="i_am_color_26e9">#000026e9</color>
+ <color name="i_am_color_26ea">#000026ea</color>
+ <color name="i_am_color_26eb">#000026eb</color>
+ <color name="i_am_color_26ec">#000026ec</color>
+ <color name="i_am_color_26ed">#000026ed</color>
+ <color name="i_am_color_26ee">#000026ee</color>
+ <color name="i_am_color_26ef">#000026ef</color>
+ <color name="i_am_color_26f0">#000026f0</color>
+ <color name="i_am_color_26f1">#000026f1</color>
+ <color name="i_am_color_26f2">#000026f2</color>
+ <color name="i_am_color_26f3">#000026f3</color>
+ <color name="i_am_color_26f4">#000026f4</color>
+ <color name="i_am_color_26f5">#000026f5</color>
+ <color name="i_am_color_26f6">#000026f6</color>
+ <color name="i_am_color_26f7">#000026f7</color>
+ <color name="i_am_color_26f8">#000026f8</color>
+ <color name="i_am_color_26f9">#000026f9</color>
+ <color name="i_am_color_26fa">#000026fa</color>
+ <color name="i_am_color_26fb">#000026fb</color>
+ <color name="i_am_color_26fc">#000026fc</color>
+ <color name="i_am_color_26fd">#000026fd</color>
+ <color name="i_am_color_26fe">#000026fe</color>
+ <color name="i_am_color_26ff">#000026ff</color>
+ <color name="i_am_color_2700">#00002700</color>
+ <color name="i_am_color_2701">#00002701</color>
+ <color name="i_am_color_2702">#00002702</color>
+ <color name="i_am_color_2703">#00002703</color>
+ <color name="i_am_color_2704">#00002704</color>
+ <color name="i_am_color_2705">#00002705</color>
+ <color name="i_am_color_2706">#00002706</color>
+ <color name="i_am_color_2707">#00002707</color>
+ <color name="i_am_color_2708">#00002708</color>
+ <color name="i_am_color_2709">#00002709</color>
+ <color name="i_am_color_270a">#0000270a</color>
+ <color name="i_am_color_270b">#0000270b</color>
+ <color name="i_am_color_270c">#0000270c</color>
+ <color name="i_am_color_270d">#0000270d</color>
+ <color name="i_am_color_270e">#0000270e</color>
+ <color name="i_am_color_270f">#0000270f</color>
+ <color name="i_am_color_2710">#00002710</color>
+</resources>
diff --git a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
index 7216244..54b79b4 100644
--- a/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
+++ b/apct-tests/perftests/core/src/android/app/ResourcesPerfTest.java
@@ -37,6 +37,7 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.util.Random;
/**
* Benchmarks for {@link android.content.res.Resources}.
@@ -222,4 +223,24 @@
state.resumeTiming();
}
}
-}
\ No newline at end of file
+
+ @Test
+ public void getIdentifier() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final Random random = new Random(System.currentTimeMillis());
+ final Context context = InstrumentationRegistry.getTargetContext();
+ final String packageName = context.getPackageName();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final int expectedInteger = random.nextInt(10001);
+ final String expectedString = Integer.toHexString(expectedInteger);
+ final String entryName = "i_am_color_" + expectedString;
+ state.resumeTiming();
+
+ final int resIdentifier = mRes.getIdentifier(entryName, "color", packageName);
+ if (resIdentifier == 0) {
+ fail("Color \"" + entryName + "\" is not found");
+ }
+ }
+ }
+}
diff --git a/apex/OWNERS b/apex/OWNERS
index b3e81b9..e867586 100644
--- a/apex/OWNERS
+++ b/apex/OWNERS
@@ -1 +1 @@
-file:platform/packages/modules/common:/OWNERS
+file:platform/packages/modules/common:/OWNERS #{LAST_RESORT_SUGGESTION}
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
deleted file mode 100644
index 1a710a98b..0000000
--- a/apex/media/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- default_visibility: [
- ":__subpackages__",
- "//frameworks/av/apex",
- "//frameworks/av/apex/testing",
- ],
- // 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"],
-}
-
-sdk {
- name: "media-module-sdk",
- bootclasspath_fragments: ["com.android.media-bootclasspath-fragment"],
- systemserverclasspath_fragments: ["com.android.media-systemserverclasspath-fragment"],
- java_sdk_libs: [
- "framework-media",
- ],
-}
diff --git a/apex/media/OWNERS b/apex/media/OWNERS
deleted file mode 100644
index 2c5965c..0000000
--- a/apex/media/OWNERS
+++ /dev/null
@@ -1,12 +0,0 @@
-# Bug component: 1344
-hdmoon@google.com
-jinpark@google.com
-klhyun@google.com
-lnilsson@google.com
-sungsoo@google.com
-
-# go/android-fwk-media-solutions for info on areas of ownership.
-include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
-
-# media reliability team packages/delivers the media mainline builds.
-include platform/frameworks/av:/media/janitors/reliability_mainline_OWNERS
diff --git a/apex/media/aidl/Android.bp b/apex/media/aidl/Android.bp
deleted file mode 100644
index 545a0cd..0000000
--- a/apex/media/aidl/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
- // 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"],
-}
-
-filegroup {
- name: "stable-media-aidl-srcs",
- srcs: ["stable/**/*.aidl"],
- path: "stable",
-}
-
-filegroup {
- name: "private-media-aidl-srcs",
- srcs: ["private/**/I*.aidl"],
- path: "private",
-}
-
-filegroup {
- name: "media-aidl-srcs",
- srcs: [
- ":private-media-aidl-srcs",
- ":stable-media-aidl-srcs",
- ],
-}
diff --git a/apex/media/aidl/private/android/media/Controller2Link.aidl b/apex/media/aidl/private/android/media/Controller2Link.aidl
deleted file mode 100644
index 64edafc..0000000
--- a/apex/media/aidl/private/android/media/Controller2Link.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-parcelable Controller2Link;
diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl
deleted file mode 100644
index fb3172b..0000000
--- a/apex/media/aidl/private/android/media/IMediaCommunicationService.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-import android.media.Session2Token;
-import android.media.IMediaCommunicationServiceCallback;
-import android.media.MediaParceledListSlice;
-
-/** {@hide} */
-interface IMediaCommunicationService {
- void notifySession2Created(in Session2Token sessionToken);
- boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid);
- MediaParceledListSlice getSession2Tokens(int userId);
-
- void registerCallback(IMediaCommunicationServiceCallback callback, String packageName);
- void unregisterCallback(IMediaCommunicationServiceCallback callback);
-}
-
diff --git a/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl b/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl
deleted file mode 100644
index e347ebf..0000000
--- a/apex/media/aidl/private/android/media/IMediaCommunicationServiceCallback.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Copyright 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.media;
-
-import android.media.Session2Token;
-import android.media.MediaParceledListSlice;
-
-/** {@hide} */
-oneway interface IMediaCommunicationServiceCallback {
- void onSession2Created(in Session2Token token);
- void onSession2Changed(in MediaParceledListSlice tokens);
-}
-
diff --git a/apex/media/aidl/private/android/media/IMediaController2.aidl b/apex/media/aidl/private/android/media/IMediaController2.aidl
deleted file mode 100644
index 42c6e70..0000000
--- a/apex/media/aidl/private/android/media/IMediaController2.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.media.Session2Command;
-
-/**
- * Interface from MediaSession2 to MediaController2.
- * <p>
- * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
- * and holds calls from session to make session owner(s) frozen.
- * @hide
- */
- // Code for AML only
-oneway interface IMediaController2 {
- void notifyConnected(int seq, in Bundle connectionResult) = 0;
- void notifyDisconnected(int seq) = 1;
- void notifyPlaybackActiveChanged(int seq, boolean playbackActive) = 2;
- void sendSessionCommand(int seq, in Session2Command command, in Bundle args,
- in ResultReceiver resultReceiver) = 3;
- void cancelSessionCommand(int seq) = 4;
- // Next Id : 5
-}
diff --git a/apex/media/aidl/private/android/media/IMediaSession2.aidl b/apex/media/aidl/private/android/media/IMediaSession2.aidl
deleted file mode 100644
index 26e717b..0000000
--- a/apex/media/aidl/private/android/media/IMediaSession2.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import android.os.Bundle;
-import android.os.ResultReceiver;
-import android.media.Controller2Link;
-import android.media.Session2Command;
-
-/**
- * Interface from MediaController2 to MediaSession2.
- * <p>
- * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
- * and holds calls from session to make session owner(s) frozen.
- * @hide
- */
- // Code for AML only
-oneway interface IMediaSession2 {
- void connect(in Controller2Link caller, int seq, in Bundle connectionRequest) = 0;
- void disconnect(in Controller2Link caller, int seq) = 1;
- void sendSessionCommand(in Controller2Link caller, int seq, in Session2Command sessionCommand,
- in Bundle args, in ResultReceiver resultReceiver) = 2;
- void cancelSessionCommand(in Controller2Link caller, int seq) = 3;
- // Next Id : 4
-}
diff --git a/apex/media/aidl/private/android/media/IMediaSession2Service.aidl b/apex/media/aidl/private/android/media/IMediaSession2Service.aidl
deleted file mode 100644
index 10ac1be..0000000
--- a/apex/media/aidl/private/android/media/IMediaSession2Service.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Bundle;
-import android.media.Controller2Link;
-
-/**
- * Interface from MediaController2 to MediaSession2Service.
- * <p>
- * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
- * and holds calls from controller to make controller owner(s) frozen.
- * @hide
- */
-oneway interface IMediaSession2Service {
- void connect(in Controller2Link caller, int seq, in Bundle connectionRequest) = 0;
- // Next Id : 1
-}
diff --git a/apex/media/aidl/private/android/media/Session2Command.aidl b/apex/media/aidl/private/android/media/Session2Command.aidl
deleted file mode 100644
index 43a7b12..0000000
--- a/apex/media/aidl/private/android/media/Session2Command.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-parcelable Session2Command;
diff --git a/apex/media/aidl/stable/android/media/MediaParceledListSlice.aidl b/apex/media/aidl/stable/android/media/MediaParceledListSlice.aidl
deleted file mode 100644
index 92d673f..0000000
--- a/apex/media/aidl/stable/android/media/MediaParceledListSlice.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-parcelable MediaParceledListSlice<T>;
diff --git a/apex/media/aidl/stable/android/media/Session2Token.aidl b/apex/media/aidl/stable/android/media/Session2Token.aidl
deleted file mode 100644
index c5980e9..0000000
--- a/apex/media/aidl/stable/android/media/Session2Token.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-parcelable Session2Token;
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
deleted file mode 100644
index d963e68..0000000
--- a/apex/media/framework/Android.bp
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- // 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: "updatable-media",
-
- srcs: [
- ":updatable-media-srcs",
- ],
-
- permitted_packages: [
- "android.media",
- ],
-
- optimize: {
- enabled: true,
- shrink: true,
- proguard_flags_files: ["updatable-media-proguard.flags"],
- },
-
- installable: true,
-
- sdk_version: "module_current",
- libs: [
- "androidx.annotation_annotation",
- "framework-annotations-lib",
- ],
- static_libs: [
- "exoplayer2-extractor",
- "mediatranscoding_aidl_interface-java",
- "modules-annotation-minsdk",
- "modules-utils-build",
- ],
- jarjar_rules: "jarjar_rules.txt",
-
- plugins: ["java_api_finder"],
-
- hostdex: true, // for hiddenapi check
- apex_available: [
- "com.android.media",
- "test_com.android.media",
- ],
- min_sdk_version: "29",
- visibility: [
- "//frameworks/av/apex:__subpackages__",
- "//frameworks/base", // For framework-all
- "//frameworks/base/apex/media/service",
- ],
-}
-
-filegroup {
- name: "updatable-media-srcs",
- srcs: [
- "java/android/media/MediaFrameworkInitializer.java",
- ":media-aidl-srcs",
- ":mediaparceledlistslice-java-srcs",
- ":mediaparser-srcs",
- ":mediasession2-java-srcs",
- ":mediatranscoding-srcs",
- ],
- visibility: ["//frameworks/base"],
-}
-
-filegroup {
- name: "mediasession2-java-srcs",
- srcs: [
- "java/android/media/Controller2Link.java",
- "java/android/media/MediaConstants.java",
- "java/android/media/MediaController2.java",
- "java/android/media/MediaSession2.java",
- "java/android/media/MediaSession2Service.java",
- "java/android/media/Session2Command.java",
- "java/android/media/Session2CommandGroup.java",
- "java/android/media/Session2Link.java",
- "java/android/media/Session2Token.java",
- "java/android/media/MediaCommunicationManager.java",
- ],
- path: "java",
-}
-
-filegroup {
- name: "mediaparceledlistslice-java-srcs",
- srcs: [
- "java/android/media/MediaParceledListSlice.java",
- "java/android/media/BaseMediaParceledListSlice.java",
- ],
- path: "java",
-}
-
-filegroup {
- name: "mediaparser-srcs",
- srcs: [
- "java/android/media/MediaParser.java",
- ],
- path: "java",
-}
-
-filegroup {
- name: "mediatranscoding-srcs",
- srcs: [
- "java/android/media/ApplicationMediaCapabilities.java",
- "java/android/media/MediaFeature.java",
- "java/android/media/MediaTranscodingManager.java",
- ],
- path: "java",
-}
-
-java_sdk_library {
- name: "framework-media",
- defaults: ["framework-module-defaults"],
-
- // This is only used to define the APIs for updatable-media.
- api_only: true,
-
- srcs: [
- ":updatable-media-srcs",
- ],
-
- impl_library_visibility: ["//frameworks/av/apex:__subpackages__"],
-}
-
-cc_library_shared {
- name: "libmediaparser-jni",
- srcs: [
- "jni/android_media_MediaParserJNI.cpp",
- ],
- header_libs: ["jni_headers"],
- shared_libs: [
- "libandroid",
- "liblog",
- "libmediametrics",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- "-Wunreachable-code",
- "-Wunused",
- ],
- apex_available: [
- "com.android.media",
- ],
- min_sdk_version: "29",
-}
diff --git a/apex/media/framework/TEST_MAPPING b/apex/media/framework/TEST_MAPPING
deleted file mode 100644
index 3d21914..0000000
--- a/apex/media/framework/TEST_MAPPING
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "presubmit": [
- {
- "name": "CtsMediaParserTestCases"
- },
- {
- "name": "CtsMediaParserHostTestCases"
- }
- ]
-}
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
deleted file mode 100644
index b7d7ed8..0000000
--- a/apex/media/framework/api/current.txt
+++ /dev/null
@@ -1,267 +0,0 @@
-// Signature format: 2.0
-package android.media {
-
- public final class ApplicationMediaCapabilities implements android.os.Parcelable {
- method @NonNull public static android.media.ApplicationMediaCapabilities createFromXml(@NonNull org.xmlpull.v1.XmlPullParser);
- method public int describeContents();
- method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
- method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
- method @NonNull public java.util.List<java.lang.String> getUnsupportedHdrTypes();
- method @NonNull public java.util.List<java.lang.String> getUnsupportedVideoMimeTypes();
- method public boolean isFormatSpecified(@NonNull String);
- method public boolean isHdrTypeSupported(@NonNull String);
- method public boolean isVideoMimeTypeSupported(@NonNull String);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
- }
-
- public static final class ApplicationMediaCapabilities.Builder {
- ctor public ApplicationMediaCapabilities.Builder();
- method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
- method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
- method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedHdrType(@NonNull String);
- method @NonNull public android.media.ApplicationMediaCapabilities.Builder addUnsupportedVideoMimeType(@NonNull String);
- method @NonNull public android.media.ApplicationMediaCapabilities build();
- }
-
- public class MediaCommunicationManager {
- method @NonNull public java.util.List<android.media.Session2Token> getSession2Tokens();
- method @IntRange(from=1) public int getVersion();
- }
-
- public class MediaController2 implements java.lang.AutoCloseable {
- method public void cancelSessionCommand(@NonNull Object);
- method public void close();
- method @Nullable public android.media.Session2Token getConnectedToken();
- method public boolean isPlaybackActive();
- method @NonNull public Object sendSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
- }
-
- public static final class MediaController2.Builder {
- ctor public MediaController2.Builder(@NonNull android.content.Context, @NonNull android.media.Session2Token);
- method @NonNull public android.media.MediaController2 build();
- method @NonNull public android.media.MediaController2.Builder setConnectionHints(@NonNull android.os.Bundle);
- method @NonNull public android.media.MediaController2.Builder setControllerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaController2.ControllerCallback);
- }
-
- public abstract static class MediaController2.ControllerCallback {
- ctor public MediaController2.ControllerCallback();
- method public void onCommandResult(@NonNull android.media.MediaController2, @NonNull Object, @NonNull android.media.Session2Command, @NonNull android.media.Session2Command.Result);
- method public void onConnected(@NonNull android.media.MediaController2, @NonNull android.media.Session2CommandGroup);
- method public void onDisconnected(@NonNull android.media.MediaController2);
- method public void onPlaybackActiveChanged(@NonNull android.media.MediaController2, boolean);
- method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaController2, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
- }
-
- public final class MediaFeature {
- ctor public MediaFeature();
- }
-
- public static final class MediaFeature.HdrType {
- field public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
- field public static final String HDR10 = "android.media.feature.hdr.hdr10";
- field public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
- field public static final String HLG = "android.media.feature.hdr.hlg";
- }
-
- public final class MediaParser {
- method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException;
- method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
- method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
- method @NonNull public android.media.metrics.LogSessionId getLogSessionId();
- method @NonNull public String getParserName();
- method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat);
- method public void release();
- method public void seek(@NonNull android.media.MediaParser.SeekPoint);
- method public void setLogSessionId(@NonNull android.media.metrics.LogSessionId);
- method @NonNull public android.media.MediaParser setParameter(@NonNull String, @NonNull Object);
- method public boolean supportsParameter(@NonNull String);
- field public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING = "android.media.mediaparser.adts.enableCbrSeeking";
- field public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "android.media.mediaparser.amr.enableCbrSeeking";
- field public static final String PARAMETER_FLAC_DISABLE_ID3 = "android.media.mediaparser.flac.disableId3";
- field public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING = "android.media.mediaparser.matroska.disableCuesSeeking";
- field public static final String PARAMETER_MP3_DISABLE_ID3 = "android.media.mediaparser.mp3.disableId3";
- field public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "android.media.mediaparser.mp3.enableCbrSeeking";
- field public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING = "android.media.mediaparser.mp3.enableIndexSeeking";
- field public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "android.media.mediaparser.mp4.ignoreEditLists";
- field public static final String PARAMETER_MP4_IGNORE_TFDT_BOX = "android.media.mediaparser.mp4.ignoreTfdtBox";
- field public static final String PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES = "android.media.mediaparser.mp4.treatVideoFramesAsKeyframes";
- field public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES = "android.media.mediaparser.ts.allowNonIdrAvcKeyframes";
- field public static final String PARAMETER_TS_DETECT_ACCESS_UNITS = "android.media.mediaparser.ts.ignoreDetectAccessUnits";
- field public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS = "android.media.mediaparser.ts.enableHdmvDtsAudioStreams";
- field public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "android.media.mediaparser.ts.ignoreAacStream";
- field public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "android.media.mediaparser.ts.ignoreAvcStream";
- field public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM = "android.media.mediaparser.ts.ignoreSpliceInfoStream";
- field public static final String PARAMETER_TS_MODE = "android.media.mediaparser.ts.mode";
- field public static final String PARSER_NAME_AC3 = "android.media.mediaparser.Ac3Parser";
- field public static final String PARSER_NAME_AC4 = "android.media.mediaparser.Ac4Parser";
- field public static final String PARSER_NAME_ADTS = "android.media.mediaparser.AdtsParser";
- field public static final String PARSER_NAME_AMR = "android.media.mediaparser.AmrParser";
- field public static final String PARSER_NAME_FLAC = "android.media.mediaparser.FlacParser";
- field public static final String PARSER_NAME_FLV = "android.media.mediaparser.FlvParser";
- field public static final String PARSER_NAME_FMP4 = "android.media.mediaparser.FragmentedMp4Parser";
- field public static final String PARSER_NAME_MATROSKA = "android.media.mediaparser.MatroskaParser";
- field public static final String PARSER_NAME_MP3 = "android.media.mediaparser.Mp3Parser";
- field public static final String PARSER_NAME_MP4 = "android.media.mediaparser.Mp4Parser";
- field public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser";
- field public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser";
- field public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser";
- field public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
- field public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser";
- field public static final int SAMPLE_FLAG_DECODE_ONLY = -2147483648; // 0x80000000
- field public static final int SAMPLE_FLAG_ENCRYPTED = 1073741824; // 0x40000000
- field public static final int SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA = 268435456; // 0x10000000
- field public static final int SAMPLE_FLAG_KEY_FRAME = 1; // 0x1
- field public static final int SAMPLE_FLAG_LAST_SAMPLE = 536870912; // 0x20000000
- }
-
- public static interface MediaParser.InputReader {
- method public long getLength();
- method public long getPosition();
- method public int read(@NonNull byte[], int, int) throws java.io.IOException;
- }
-
- public static interface MediaParser.OutputConsumer {
- method public void onSampleCompleted(int, long, int, int, int, @Nullable android.media.MediaCodec.CryptoInfo);
- method public void onSampleDataFound(int, @NonNull android.media.MediaParser.InputReader) throws java.io.IOException;
- method public void onSeekMapFound(@NonNull android.media.MediaParser.SeekMap);
- method public void onTrackCountFound(int);
- method public void onTrackDataFound(int, @NonNull android.media.MediaParser.TrackData);
- }
-
- public static final class MediaParser.ParsingException extends java.io.IOException {
- }
-
- public static final class MediaParser.SeekMap {
- method public long getDurationMicros();
- method @NonNull public android.util.Pair<android.media.MediaParser.SeekPoint,android.media.MediaParser.SeekPoint> getSeekPoints(long);
- method public boolean isSeekable();
- field public static final int UNKNOWN_DURATION = -2147483648; // 0x80000000
- }
-
- public static final class MediaParser.SeekPoint {
- field @NonNull public static final android.media.MediaParser.SeekPoint START;
- field public final long position;
- field public final long timeMicros;
- }
-
- public static interface MediaParser.SeekableInputReader extends android.media.MediaParser.InputReader {
- method public void seekToPosition(long);
- }
-
- public static final class MediaParser.TrackData {
- field @Nullable public final android.media.DrmInitData drmInitData;
- field @NonNull public final android.media.MediaFormat mediaFormat;
- }
-
- public static final class MediaParser.UnrecognizedInputFormatException extends java.io.IOException {
- }
-
- public class MediaSession2 implements java.lang.AutoCloseable {
- method public void broadcastSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
- method public void cancelSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object);
- method public void close();
- method @NonNull public java.util.List<android.media.MediaSession2.ControllerInfo> getConnectedControllers();
- method @NonNull public String getId();
- method @NonNull public android.media.Session2Token getToken();
- method public boolean isPlaybackActive();
- method @NonNull public Object sendSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
- method public void setPlaybackActive(boolean);
- }
-
- public static final class MediaSession2.Builder {
- ctor public MediaSession2.Builder(@NonNull android.content.Context);
- method @NonNull public android.media.MediaSession2 build();
- method @NonNull public android.media.MediaSession2.Builder setExtras(@NonNull android.os.Bundle);
- method @NonNull public android.media.MediaSession2.Builder setId(@NonNull String);
- method @NonNull public android.media.MediaSession2.Builder setSessionActivity(@Nullable android.app.PendingIntent);
- method @NonNull public android.media.MediaSession2.Builder setSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaSession2.SessionCallback);
- }
-
- public static final class MediaSession2.ControllerInfo {
- method @NonNull public android.os.Bundle getConnectionHints();
- method @NonNull public String getPackageName();
- method @NonNull public android.media.session.MediaSessionManager.RemoteUserInfo getRemoteUserInfo();
- method public int getUid();
- }
-
- public abstract static class MediaSession2.SessionCallback {
- ctor public MediaSession2.SessionCallback();
- method public void onCommandResult(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object, @NonNull android.media.Session2Command, @NonNull android.media.Session2Command.Result);
- method @Nullable public android.media.Session2CommandGroup onConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
- method public void onDisconnected(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
- method public void onPostConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
- method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
- }
-
- public abstract class MediaSession2Service extends android.app.Service {
- ctor public MediaSession2Service();
- method public final void addSession(@NonNull android.media.MediaSession2);
- method @NonNull public final java.util.List<android.media.MediaSession2> getSessions();
- method @CallSuper @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
- method @Nullable public abstract android.media.MediaSession2 onGetSession(@NonNull android.media.MediaSession2.ControllerInfo);
- method @Nullable public abstract android.media.MediaSession2Service.MediaNotification onUpdateNotification(@NonNull android.media.MediaSession2);
- method public final void removeSession(@NonNull android.media.MediaSession2);
- field public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service";
- }
-
- public static class MediaSession2Service.MediaNotification {
- ctor public MediaSession2Service.MediaNotification(int, @NonNull android.app.Notification);
- method @NonNull public android.app.Notification getNotification();
- method public int getNotificationId();
- }
-
- public final class Session2Command implements android.os.Parcelable {
- ctor public Session2Command(int);
- ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle);
- method public int describeContents();
- method public int getCommandCode();
- method @Nullable public String getCustomAction();
- method @Nullable public android.os.Bundle getCustomExtras();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int COMMAND_CODE_CUSTOM = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Command> CREATOR;
- }
-
- public static final class Session2Command.Result {
- ctor public Session2Command.Result(int, @Nullable android.os.Bundle);
- method public int getResultCode();
- method @Nullable public android.os.Bundle getResultData();
- field public static final int RESULT_ERROR_UNKNOWN_ERROR = -1; // 0xffffffff
- field public static final int RESULT_INFO_SKIPPED = 1; // 0x1
- field public static final int RESULT_SUCCESS = 0; // 0x0
- }
-
- public final class Session2CommandGroup implements android.os.Parcelable {
- method public int describeContents();
- method @NonNull public java.util.Set<android.media.Session2Command> getCommands();
- method public boolean hasCommand(@NonNull android.media.Session2Command);
- method public boolean hasCommand(int);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2CommandGroup> CREATOR;
- }
-
- public static final class Session2CommandGroup.Builder {
- ctor public Session2CommandGroup.Builder();
- ctor public Session2CommandGroup.Builder(@NonNull android.media.Session2CommandGroup);
- method @NonNull public android.media.Session2CommandGroup.Builder addCommand(@NonNull android.media.Session2Command);
- method @NonNull public android.media.Session2CommandGroup build();
- method @NonNull public android.media.Session2CommandGroup.Builder removeCommand(@NonNull android.media.Session2Command);
- }
-
- public final class Session2Token implements android.os.Parcelable {
- ctor public Session2Token(@NonNull android.content.Context, @NonNull android.content.ComponentName);
- method public int describeContents();
- method @NonNull public android.os.Bundle getExtras();
- method @NonNull public String getPackageName();
- method @Nullable public String getServiceName();
- method public int getType();
- method public int getUid();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.Session2Token> CREATOR;
- field public static final int TYPE_SESSION = 0; // 0x0
- field public static final int TYPE_SESSION_SERVICE = 1; // 0x1
- }
-
-}
-
diff --git a/apex/media/framework/api/module-lib-current.txt b/apex/media/framework/api/module-lib-current.txt
deleted file mode 100644
index eb6397a1..0000000
--- a/apex/media/framework/api/module-lib-current.txt
+++ /dev/null
@@ -1,30 +0,0 @@
-// Signature format: 2.0
-package android.media {
-
- public class MediaCommunicationManager {
- method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void registerSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaCommunicationManager.SessionCallback);
- method public void unregisterSessionCallback(@NonNull android.media.MediaCommunicationManager.SessionCallback);
- }
-
- public static interface MediaCommunicationManager.SessionCallback {
- method public default void onSession2TokenCreated(@NonNull android.media.Session2Token);
- method public default void onSession2TokensChanged(@NonNull java.util.List<android.media.Session2Token>);
- }
-
- public class MediaFrameworkInitializer {
- method public static void registerServiceWrappers();
- method public static void setMediaServiceManager(@NonNull android.media.MediaServiceManager);
- }
-
- @Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
- ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
- method @Deprecated public java.util.List<T> getList();
- method @Deprecated public void setInlineCountLimit(int);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
- }
-
-}
-
diff --git a/apex/media/framework/api/module-lib-removed.txt b/apex/media/framework/api/module-lib-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/framework/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/framework/api/system-current.txt b/apex/media/framework/api/system-current.txt
deleted file mode 100644
index 6eea769..0000000
--- a/apex/media/framework/api/system-current.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-// Signature format: 2.0
-package android.media {
-
- public final class MediaTranscodingManager {
- method @Nullable public android.media.MediaTranscodingManager.TranscodingSession enqueueRequest(@NonNull android.media.MediaTranscodingManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodingManager.OnTranscodingFinishedListener);
- }
-
- @java.lang.FunctionalInterface public static interface MediaTranscodingManager.OnTranscodingFinishedListener {
- method public void onTranscodingFinished(@NonNull android.media.MediaTranscodingManager.TranscodingSession);
- }
-
- public abstract static class MediaTranscodingManager.TranscodingRequest {
- method public int getClientPid();
- method public int getClientUid();
- method @Nullable public android.os.ParcelFileDescriptor getDestinationFileDescriptor();
- method @NonNull public android.net.Uri getDestinationUri();
- method @Nullable public android.os.ParcelFileDescriptor getSourceFileDescriptor();
- method @NonNull public android.net.Uri getSourceUri();
- }
-
- public static class MediaTranscodingManager.TranscodingRequest.VideoFormatResolver {
- ctor public MediaTranscodingManager.TranscodingRequest.VideoFormatResolver(@NonNull android.media.ApplicationMediaCapabilities, @NonNull android.media.MediaFormat);
- method @Nullable public android.media.MediaFormat resolveVideoFormat();
- method public boolean shouldTranscode();
- }
-
- public static final class MediaTranscodingManager.TranscodingSession {
- method public boolean addClientUid(int);
- method public void cancel();
- method @NonNull public java.util.List<java.lang.Integer> getClientUids();
- method public int getErrorCode();
- method @IntRange(from=0, to=100) public int getProgress();
- method public int getResult();
- method public int getSessionId();
- method public int getStatus();
- method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodingManager.TranscodingSession.OnProgressUpdateListener);
- field public static final int ERROR_DROPPED_BY_SERVICE = 1; // 0x1
- field public static final int ERROR_NONE = 0; // 0x0
- field public static final int ERROR_SERVICE_DIED = 2; // 0x2
- field public static final int RESULT_CANCELED = 4; // 0x4
- field public static final int RESULT_ERROR = 3; // 0x3
- field public static final int RESULT_NONE = 1; // 0x1
- field public static final int RESULT_SUCCESS = 2; // 0x2
- field public static final int STATUS_FINISHED = 3; // 0x3
- field public static final int STATUS_PAUSED = 4; // 0x4
- field public static final int STATUS_PENDING = 1; // 0x1
- field public static final int STATUS_RUNNING = 2; // 0x2
- }
-
- @java.lang.FunctionalInterface public static interface MediaTranscodingManager.TranscodingSession.OnProgressUpdateListener {
- method public void onProgressUpdate(@NonNull android.media.MediaTranscodingManager.TranscodingSession, @IntRange(from=0, to=100) int);
- }
-
- public static final class MediaTranscodingManager.VideoTranscodingRequest extends android.media.MediaTranscodingManager.TranscodingRequest {
- method @NonNull public android.media.MediaFormat getVideoTrackFormat();
- }
-
- public static final class MediaTranscodingManager.VideoTranscodingRequest.Builder {
- ctor public MediaTranscodingManager.VideoTranscodingRequest.Builder(@NonNull android.net.Uri, @NonNull android.net.Uri, @NonNull android.media.MediaFormat);
- method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest build();
- method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setClientPid(int);
- method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setClientUid(int);
- method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setDestinationFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
- method @NonNull public android.media.MediaTranscodingManager.VideoTranscodingRequest.Builder setSourceFileDescriptor(@NonNull android.os.ParcelFileDescriptor);
- }
-
-}
-
diff --git a/apex/media/framework/api/system-removed.txt b/apex/media/framework/api/system-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/framework/api/system-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/framework/jarjar_rules.txt b/apex/media/framework/jarjar_rules.txt
deleted file mode 100644
index 91489dc..0000000
--- a/apex/media/framework/jarjar_rules.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-rule com.android.modules.** android.media.internal.@1
-rule com.google.android.exoplayer2.** android.media.internal.exo.@1
diff --git a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
deleted file mode 100644
index 97fa0ec..0000000
--- a/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-import android.content.ContentResolver;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import com.android.modules.annotation.MinSdk;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- ApplicationMediaCapabilities is an immutable class that encapsulates an application's capabilities
- for handling newer video codec format and media features.
-
- <p>
- Android 12 introduces Compatible media transcoding feature. See
- <a href="https://developer.android.com/about/versions/12/features#compatible_media_transcoding">
- Compatible media transcoding</a>. By default, Android assumes apps can support playback of all
- media formats. Apps that would like to request that media be transcoded into a more compatible
- format should declare their media capabilities in a media_capabilities.xml resource file and add it
- as a property tag in the AndroidManifest.xml file. Here is a example:
- <pre>
- {@code
- <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="true"/>
- <format android:name="HDR10" supported="false"/>
- <format android:name="HDR10Plus" supported="false"/>
- </media-capabilities>
- }
- </pre>
- The ApplicationMediaCapabilities class is generated from this xml and used by the platform to
- represent an application's media capabilities in order to determine whether modern media files need
- to be transcoded for that application.
- </p>
-
- <p>
- ApplicationMediaCapabilities objects can also be built by applications at runtime for use with
- {@link ContentResolver#openTypedAssetFileDescriptor(Uri, String, Bundle)} to provide more
- control over the transcoding that is built into the platform. ApplicationMediaCapabilities
- provided by applications at runtime like this override the default manifest capabilities for that
- media access.The object could be build either through {@link #createFromXml(XmlPullParser)} or
- through the builder class {@link ApplicationMediaCapabilities.Builder}
-
- <h3> Video Codec Support</h3>
- <p>
- Newer video codes include HEVC, VP9 and AV1. Application only needs to indicate their support
- for newer format with this class as they are assumed to support older format like h.264.
-
- <h3>Capability of handling HDR(high dynamic range) video</h3>
- <p>
- There are four types of HDR video(Dolby-Vision, HDR10, HDR10+, HLG) supported by the platform,
- application will only need to specify individual types they supported.
- */
-@MinSdk(Build.VERSION_CODES.S)
-public final class ApplicationMediaCapabilities implements Parcelable {
- private static final String TAG = "ApplicationMediaCapabilities";
-
- /** List of supported video codec mime types. */
- private Set<String> mSupportedVideoMimeTypes = new HashSet<>();
-
- /** List of unsupported video codec mime types. */
- private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
-
- /** List of supported hdr types. */
- private Set<String> mSupportedHdrTypes = new HashSet<>();
-
- /** List of unsupported hdr types. */
- private Set<String> mUnsupportedHdrTypes = new HashSet<>();
-
- private boolean mIsSlowMotionSupported = false;
-
- private ApplicationMediaCapabilities(Builder b) {
- mSupportedVideoMimeTypes.addAll(b.getSupportedVideoMimeTypes());
- mUnsupportedVideoMimeTypes.addAll(b.getUnsupportedVideoMimeTypes());
- mSupportedHdrTypes.addAll(b.getSupportedHdrTypes());
- mUnsupportedHdrTypes.addAll(b.getUnsupportedHdrTypes());
- mIsSlowMotionSupported = b.mIsSlowMotionSupported;
- }
-
- /**
- * Query if a video codec format is supported by the application.
- * <p>
- * If the application has not specified supporting the format or not, this will return false.
- * Use {@link #isFormatSpecified(String)} to query if a format is specified or not.
- *
- * @param videoMime The mime type of the video codec format. Must be the one used in
- * {@link MediaFormat#KEY_MIME}.
- * @return true if application supports the video codec format, false otherwise.
- */
- public boolean isVideoMimeTypeSupported(
- @NonNull String videoMime) {
- if (mSupportedVideoMimeTypes.contains(videoMime.toLowerCase())) {
- return true;
- }
- return false;
- }
-
- /**
- * Query if a HDR type is supported by the application.
- * <p>
- * If the application has not specified supporting the format or not, this will return false.
- * Use {@link #isFormatSpecified(String)} to query if a format is specified or not.
- *
- * @param hdrType The type of the HDR format.
- * @return true if application supports the HDR format, false otherwise.
- */
- public boolean isHdrTypeSupported(
- @NonNull @MediaFeature.MediaHdrType String hdrType) {
- if (mSupportedHdrTypes.contains(hdrType)) {
- return true;
- }
- return false;
- }
-
- /**
- * Query if a format is specified by the application.
- * <p>
- * The format could be either the video format or the hdr format.
- *
- * @param format The name of the format.
- * @return true if application specifies the format, false otherwise.
- */
- public boolean isFormatSpecified(@NonNull String format) {
- if (mSupportedVideoMimeTypes.contains(format) || mUnsupportedVideoMimeTypes.contains(format)
- || mSupportedHdrTypes.contains(format) || mUnsupportedHdrTypes.contains(format)) {
- return true;
-
- }
- return false;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- // Write out the supported video mime types.
- dest.writeInt(mSupportedVideoMimeTypes.size());
- for (String cap : mSupportedVideoMimeTypes) {
- dest.writeString(cap);
- }
- // Write out the unsupported video mime types.
- dest.writeInt(mUnsupportedVideoMimeTypes.size());
- for (String cap : mUnsupportedVideoMimeTypes) {
- dest.writeString(cap);
- }
- // Write out the supported hdr types.
- dest.writeInt(mSupportedHdrTypes.size());
- for (String cap : mSupportedHdrTypes) {
- dest.writeString(cap);
- }
- // Write out the unsupported hdr types.
- dest.writeInt(mUnsupportedHdrTypes.size());
- for (String cap : mUnsupportedHdrTypes) {
- dest.writeString(cap);
- }
- // Write out the supported slow motion.
- dest.writeBoolean(mIsSlowMotionSupported);
- }
-
- @Override
- public String toString() {
- String caps = new String(
- "Supported Video MimeTypes: " + mSupportedVideoMimeTypes.toString());
- caps += "Unsupported Video MimeTypes: " + mUnsupportedVideoMimeTypes.toString();
- caps += "Supported HDR types: " + mSupportedHdrTypes.toString();
- caps += "Unsupported HDR types: " + mUnsupportedHdrTypes.toString();
- caps += "Supported slow motion: " + mIsSlowMotionSupported;
- return caps;
- }
-
- @NonNull
- public static final Creator<ApplicationMediaCapabilities> CREATOR =
- new Creator<ApplicationMediaCapabilities>() {
- public ApplicationMediaCapabilities createFromParcel(Parcel in) {
- ApplicationMediaCapabilities.Builder builder =
- new ApplicationMediaCapabilities.Builder();
-
- // Parse supported video codec mime types.
- int count = in.readInt();
- for (int readCount = 0; readCount < count; ++readCount) {
- builder.addSupportedVideoMimeType(in.readString());
- }
-
- // Parse unsupported video codec mime types.
- count = in.readInt();
- for (int readCount = 0; readCount < count; ++readCount) {
- builder.addUnsupportedVideoMimeType(in.readString());
- }
-
- // Parse supported hdr types.
- count = in.readInt();
- for (int readCount = 0; readCount < count; ++readCount) {
- builder.addSupportedHdrType(in.readString());
- }
-
- // Parse unsupported hdr types.
- count = in.readInt();
- for (int readCount = 0; readCount < count; ++readCount) {
- builder.addUnsupportedHdrType(in.readString());
- }
-
- boolean supported = in.readBoolean();
- builder.setSlowMotionSupported(supported);
-
- return builder.build();
- }
-
- public ApplicationMediaCapabilities[] newArray(int size) {
- return new ApplicationMediaCapabilities[size];
- }
- };
-
- /**
- * Query the video codec mime types supported by the application.
- * @return List of supported video codec mime types. The list will be empty if there are none.
- */
- @NonNull
- public List<String> getSupportedVideoMimeTypes() {
- return new ArrayList<>(mSupportedVideoMimeTypes);
- }
-
- /**
- * Query the video codec mime types that are not supported by the application.
- * @return List of unsupported video codec mime types. The list will be empty if there are none.
- */
- @NonNull
- public List<String> getUnsupportedVideoMimeTypes() {
- return new ArrayList<>(mUnsupportedVideoMimeTypes);
- }
-
- /**
- * Query all hdr types that are supported by the application.
- * @return List of supported hdr types. The list will be empty if there are none.
- */
- @NonNull
- public List<String> getSupportedHdrTypes() {
- return new ArrayList<>(mSupportedHdrTypes);
- }
-
- /**
- * Query all hdr types that are not supported by the application.
- * @return List of unsupported hdr types. The list will be empty if there are none.
- */
- @NonNull
- public List<String> getUnsupportedHdrTypes() {
- return new ArrayList<>(mUnsupportedHdrTypes);
- }
-
- /**
- * Whether handling of slow-motion video is supported
- * @hide
- */
- public boolean isSlowMotionSupported() {
- return mIsSlowMotionSupported;
- }
-
- /**
- * Creates {@link ApplicationMediaCapabilities} from an xml.
- *
- * The xml's syntax is the same as the media_capabilities.xml used by the AndroidManifest.xml.
- * <p> Here is an example:
- *
- * <pre>
- * {@code
- * <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- * <format android:name="HEVC" supported="true"/>
- * <format android:name="HDR10" supported="false"/>
- * <format android:name="HDR10Plus" supported="false"/>
- * </media-capabilities>
- * }
- * </pre>
- * <p>
- *
- * @param xmlParser The underlying {@link XmlPullParser} that will read the xml.
- * @return An ApplicationMediaCapabilities object.
- * @throws UnsupportedOperationException if the capabilities in xml config are invalid or
- * incompatible.
- */
- // TODO: Add developer.android.com link for the format of the xml.
- @NonNull
- public static ApplicationMediaCapabilities createFromXml(@NonNull XmlPullParser xmlParser) {
- ApplicationMediaCapabilities.Builder builder = new ApplicationMediaCapabilities.Builder();
- builder.parseXml(xmlParser);
- return builder.build();
- }
-
- /**
- * Builder class for {@link ApplicationMediaCapabilities} objects.
- * Use this class to configure and create an ApplicationMediaCapabilities instance. Builder
- * could be created from an existing ApplicationMediaCapabilities object, from a xml file or
- * MediaCodecList.
- * //TODO(hkuang): Add xml parsing support to the builder.
- */
- public final static class Builder {
- /** List of supported video codec mime types. */
- private Set<String> mSupportedVideoMimeTypes = new HashSet<>();
-
- /** List of supported hdr types. */
- private Set<String> mSupportedHdrTypes = new HashSet<>();
-
- /** List of unsupported video codec mime types. */
- private Set<String> mUnsupportedVideoMimeTypes = new HashSet<>();
-
- /** List of unsupported hdr types. */
- private Set<String> mUnsupportedHdrTypes = new HashSet<>();
-
- private boolean mIsSlowMotionSupported = false;
-
- /* Map to save the format read from the xml. */
- private Map<String, Boolean> mFormatSupportedMap = new HashMap<String, Boolean>();
-
- /**
- * Constructs a new Builder with all the supports default to false.
- */
- public Builder() {
- }
-
- private void parseXml(@NonNull XmlPullParser xmlParser)
- throws UnsupportedOperationException {
- if (xmlParser == null) {
- throw new IllegalArgumentException("XmlParser must not be null");
- }
-
- try {
- while (xmlParser.next() != XmlPullParser.START_TAG) {
- continue;
- }
-
- // Validates the tag is "media-capabilities".
- if (!xmlParser.getName().equals("media-capabilities")) {
- throw new UnsupportedOperationException("Invalid tag");
- }
-
- xmlParser.next();
- while (xmlParser.getEventType() != XmlPullParser.END_TAG) {
- while (xmlParser.getEventType() != XmlPullParser.START_TAG) {
- if (xmlParser.getEventType() == XmlPullParser.END_DOCUMENT) {
- return;
- }
- xmlParser.next();
- }
-
- // Validates the tag is "format".
- if (xmlParser.getName().equals("format")) {
- parseFormatTag(xmlParser);
- } else {
- throw new UnsupportedOperationException("Invalid tag");
- }
- while (xmlParser.getEventType() != XmlPullParser.END_TAG) {
- xmlParser.next();
- }
- xmlParser.next();
- }
- } catch (XmlPullParserException xppe) {
- throw new UnsupportedOperationException("Ill-formatted xml file");
- } catch (java.io.IOException ioe) {
- throw new UnsupportedOperationException("Unable to read xml file");
- }
- }
-
- private void parseFormatTag(XmlPullParser xmlParser) {
- String name = null;
- String supported = null;
- for (int i = 0; i < xmlParser.getAttributeCount(); i++) {
- String attrName = xmlParser.getAttributeName(i);
- if (attrName.equals("name")) {
- name = xmlParser.getAttributeValue(i);
- } else if (attrName.equals("supported")) {
- supported = xmlParser.getAttributeValue(i);
- } else {
- throw new UnsupportedOperationException("Invalid attribute name " + attrName);
- }
- }
-
- if (name != null && supported != null) {
- if (!supported.equals("true") && !supported.equals("false")) {
- throw new UnsupportedOperationException(
- ("Supported value must be either true or false"));
- }
- boolean isSupported = Boolean.parseBoolean(supported);
-
- // Check if the format is already found before.
- if (mFormatSupportedMap.get(name) != null && mFormatSupportedMap.get(name)
- != isSupported) {
- throw new UnsupportedOperationException(
- "Format: " + name + " has conflict supported value");
- }
-
- switch (name) {
- case "HEVC":
- if (isSupported) {
- mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
- } else {
- mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
- }
- break;
- case "VP9":
- if (isSupported) {
- mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
- } else {
- mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_VP9);
- }
- break;
- case "AV1":
- if (isSupported) {
- mSupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
- } else {
- mUnsupportedVideoMimeTypes.add(MediaFormat.MIMETYPE_VIDEO_AV1);
- }
- break;
- case "HDR10":
- if (isSupported) {
- mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
- } else {
- mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10);
- }
- break;
- case "HDR10Plus":
- if (isSupported) {
- mSupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
- } else {
- mUnsupportedHdrTypes.add(MediaFeature.HdrType.HDR10_PLUS);
- }
- break;
- case "Dolby-Vision":
- if (isSupported) {
- mSupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
- } else {
- mUnsupportedHdrTypes.add(MediaFeature.HdrType.DOLBY_VISION);
- }
- break;
- case "HLG":
- if (isSupported) {
- mSupportedHdrTypes.add(MediaFeature.HdrType.HLG);
- } else {
- mUnsupportedHdrTypes.add(MediaFeature.HdrType.HLG);
- }
- break;
- case "SlowMotion":
- mIsSlowMotionSupported = isSupported;
- break;
- default:
- Log.w(TAG, "Invalid format name " + name);
- }
- // Save the name and isSupported into the map for validate later.
- mFormatSupportedMap.put(name, isSupported);
- } else {
- throw new UnsupportedOperationException(
- "Format name and supported must both be specified");
- }
- }
-
- /**
- * Builds a {@link ApplicationMediaCapabilities} object.
- *
- * @return a new {@link ApplicationMediaCapabilities} instance successfully initialized
- * with all the parameters set on this <code>Builder</code>.
- * @throws UnsupportedOperationException if the parameters set on the
- * <code>Builder</code> were incompatible, or if they
- * are not supported by the
- * device.
- */
- @NonNull
- public ApplicationMediaCapabilities build() {
- Log.d(TAG,
- "Building ApplicationMediaCapabilities with: (Supported HDR: "
- + mSupportedHdrTypes.toString() + " Unsupported HDR: "
- + mUnsupportedHdrTypes.toString() + ") (Supported Codec: "
- + " " + mSupportedVideoMimeTypes.toString() + " Unsupported Codec:"
- + mUnsupportedVideoMimeTypes.toString() + ") "
- + mIsSlowMotionSupported);
-
- // If hdr is supported, application must also support hevc.
- if (!mSupportedHdrTypes.isEmpty() && !mSupportedVideoMimeTypes.contains(
- MediaFormat.MIMETYPE_VIDEO_HEVC)) {
- throw new UnsupportedOperationException("Only support HEVC mime type");
- }
- return new ApplicationMediaCapabilities(this);
- }
-
- /**
- * Adds a supported video codec mime type.
- *
- * @param codecMime Supported codec mime types. Must be one of the mime type defined
- * in {@link MediaFormat}.
- * @throws IllegalArgumentException if mime type is not valid.
- */
- @NonNull
- public Builder addSupportedVideoMimeType(
- @NonNull String codecMime) {
- mSupportedVideoMimeTypes.add(codecMime);
- return this;
- }
-
- private List<String> getSupportedVideoMimeTypes() {
- return new ArrayList<>(mSupportedVideoMimeTypes);
- }
-
- private boolean isValidVideoCodecMimeType(@NonNull String codecMime) {
- if (!codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)
- && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_VP9)
- && !codecMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) {
- return false;
- }
- return true;
- }
-
- /**
- * Adds an unsupported video codec mime type.
- *
- * @param codecMime Unsupported codec mime type. Must be one of the mime type defined
- * in {@link MediaFormat}.
- * @throws IllegalArgumentException if mime type is not valid.
- */
- @NonNull
- public Builder addUnsupportedVideoMimeType(
- @NonNull String codecMime) {
- if (!isValidVideoCodecMimeType(codecMime)) {
- throw new IllegalArgumentException("Invalid codec mime type: " + codecMime);
- }
- mUnsupportedVideoMimeTypes.add(codecMime);
- return this;
- }
-
- private List<String> getUnsupportedVideoMimeTypes() {
- return new ArrayList<>(mUnsupportedVideoMimeTypes);
- }
-
- /**
- * Adds a supported hdr type.
- *
- * @param hdrType Supported hdr type. Must be one of the String defined in
- * {@link MediaFeature.HdrType}.
- * @throws IllegalArgumentException if hdrType is not valid.
- */
- @NonNull
- public Builder addSupportedHdrType(
- @NonNull @MediaFeature.MediaHdrType String hdrType) {
- if (!isValidVideoCodecHdrType(hdrType)) {
- throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
- }
- mSupportedHdrTypes.add(hdrType);
- return this;
- }
-
- private List<String> getSupportedHdrTypes() {
- return new ArrayList<>(mSupportedHdrTypes);
- }
-
- private boolean isValidVideoCodecHdrType(@NonNull String hdrType) {
- if (!hdrType.equals(MediaFeature.HdrType.DOLBY_VISION)
- && !hdrType.equals(MediaFeature.HdrType.HDR10)
- && !hdrType.equals(MediaFeature.HdrType.HDR10_PLUS)
- && !hdrType.equals(MediaFeature.HdrType.HLG)) {
- return false;
- }
- return true;
- }
-
- /**
- * Adds an unsupported hdr type.
- *
- * @param hdrType Unsupported hdr type. Must be one of the String defined in
- * {@link MediaFeature.HdrType}.
- * @throws IllegalArgumentException if hdrType is not valid.
- */
- @NonNull
- public Builder addUnsupportedHdrType(
- @NonNull @MediaFeature.MediaHdrType String hdrType) {
- if (!isValidVideoCodecHdrType(hdrType)) {
- throw new IllegalArgumentException("Invalid hdr type: " + hdrType);
- }
- mUnsupportedHdrTypes.add(hdrType);
- return this;
- }
-
- private List<String> getUnsupportedHdrTypes() {
- return new ArrayList<>(mUnsupportedHdrTypes);
- }
-
- /**
- * Sets whether slow-motion video is supported.
- * If an application indicates support for slow-motion, it is application's responsibility
- * to parse the slow-motion videos using their own parser or using support library.
- * @see android.media.MediaFormat#KEY_SLOW_MOTION_MARKERS
- * @hide
- */
- @NonNull
- public Builder setSlowMotionSupported(boolean slowMotionSupported) {
- mIsSlowMotionSupported = slowMotionSupported;
- return this;
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java b/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java
deleted file mode 100644
index fb66609..0000000
--- a/apex/media/framework/java/android/media/BaseMediaParceledListSlice.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This is a copied version of BaseParceledListSlice in framework with hidden API usages
- * removed.
- *
- * Transfer a large list of Parcelable objects across an IPC. Splits into
- * multiple transactions if needed.
- *
- * Caveat: for efficiency and security, all elements must be the same concrete type.
- * In order to avoid writing the class name of each object, we must ensure that
- * each object is the same type, or else unparceling then reparceling the data may yield
- * a different result if the class name encoded in the Parcelable is a Base type.
- * See b/17671747.
- *
- * @hide
- */
-abstract class BaseMediaParceledListSlice<T> implements Parcelable {
- private static String TAG = "BaseMediaParceledListSlice";
- private static boolean DEBUG = false;
-
- /*
- * TODO get this number from somewhere else. For now set it to a quarter of
- * the 1MB limit.
- */
- // private static final int MAX_IPC_SIZE = IBinder.getSuggestedMaxIpcSizeBytes();
- private static final int MAX_IPC_SIZE = 64 * 1024;
-
- private final List<T> mList;
-
- private int mInlineCountLimit = Integer.MAX_VALUE;
-
- public BaseMediaParceledListSlice(List<T> list) {
- mList = list;
- }
-
- @SuppressWarnings("unchecked")
- BaseMediaParceledListSlice(Parcel p, ClassLoader loader) {
- final int N = p.readInt();
- mList = new ArrayList<T>(N);
- if (DEBUG) Log.d(TAG, "Retrieving " + N + " items");
- if (N <= 0) {
- return;
- }
-
- Parcelable.Creator<?> creator = readParcelableCreator(p, loader);
- Class<?> listElementClass = null;
-
- int i = 0;
- while (i < N) {
- if (p.readInt() == 0) {
- break;
- }
-
- final T parcelable = readCreator(creator, p, loader);
- if (listElementClass == null) {
- listElementClass = parcelable.getClass();
- } else {
- verifySameType(listElementClass, parcelable.getClass());
- }
-
- mList.add(parcelable);
-
- if (DEBUG) Log.d(TAG, "Read inline #" + i + ": " + mList.get(mList.size()-1));
- i++;
- }
- if (i >= N) {
- return;
- }
- final IBinder retriever = p.readStrongBinder();
- while (i < N) {
- if (DEBUG) Log.d(TAG, "Reading more @" + i + " of " + N + ": retriever=" + retriever);
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInt(i);
- try {
- retriever.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
- } catch (RemoteException e) {
- Log.w(TAG, "Failure retrieving array; only received " + i + " of " + N, e);
- return;
- }
- while (i < N && reply.readInt() != 0) {
- final T parcelable = readCreator(creator, reply, loader);
- verifySameType(listElementClass, parcelable.getClass());
-
- mList.add(parcelable);
-
- if (DEBUG) Log.d(TAG, "Read extra #" + i + ": " + mList.get(mList.size()-1));
- i++;
- }
- reply.recycle();
- data.recycle();
- }
- }
-
- private T readCreator(Parcelable.Creator<?> creator, Parcel p, ClassLoader loader) {
- if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
- Parcelable.ClassLoaderCreator<?> classLoaderCreator =
- (Parcelable.ClassLoaderCreator<?>) creator;
- return (T) classLoaderCreator.createFromParcel(p, loader);
- }
- return (T) creator.createFromParcel(p);
- }
-
- private static void verifySameType(final Class<?> expected, final Class<?> actual) {
- if (!actual.equals(expected)) {
- throw new IllegalArgumentException("Can't unparcel type "
- + (actual == null ? null : actual.getName()) + " in list of type "
- + (expected == null ? null : expected.getName()));
- }
- }
-
- public List<T> getList() {
- return mList;
- }
-
- /**
- * Set a limit on the maximum number of entries in the array that will be included
- * inline in the initial parcelling of this object.
- */
- public void setInlineCountLimit(int maxCount) {
- mInlineCountLimit = maxCount;
- }
-
- /**
- * Write this to another Parcel. Note that this discards the internal Parcel
- * and should not be used anymore. This is so we can pass this to a Binder
- * where we won't have a chance to call recycle on this.
- */
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- final int N = mList.size();
- final int callFlags = flags;
- dest.writeInt(N);
- if (DEBUG) Log.d(TAG, "Writing " + N + " items");
- if (N > 0) {
- final Class<?> listElementClass = mList.get(0).getClass();
- writeParcelableCreator(mList.get(0), dest);
- int i = 0;
- while (i < N && i < mInlineCountLimit && dest.dataSize() < MAX_IPC_SIZE) {
- dest.writeInt(1);
-
- final T parcelable = mList.get(i);
- verifySameType(listElementClass, parcelable.getClass());
- writeElement(parcelable, dest, callFlags);
-
- if (DEBUG) Log.d(TAG, "Wrote inline #" + i + ": " + mList.get(i));
- i++;
- }
- if (i < N) {
- dest.writeInt(0);
- Binder retriever = new Binder() {
- @Override
- protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- if (code != FIRST_CALL_TRANSACTION) {
- return super.onTransact(code, data, reply, flags);
- }
- int i = data.readInt();
- if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
- while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
- reply.writeInt(1);
-
- final T parcelable = mList.get(i);
- verifySameType(listElementClass, parcelable.getClass());
- writeElement(parcelable, reply, callFlags);
-
- if (DEBUG) Log.d(TAG, "Wrote extra #" + i + ": " + mList.get(i));
- i++;
- }
- if (i < N) {
- if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
- reply.writeInt(0);
- }
- return true;
- }
- };
- if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N + ": retriever=" + retriever);
- dest.writeStrongBinder(retriever);
- }
- }
- }
-
- abstract void writeElement(T parcelable, Parcel reply, int callFlags);
-
- abstract void writeParcelableCreator(T parcelable, Parcel dest);
-
- abstract Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader);
-}
diff --git a/apex/media/framework/java/android/media/BufferingParams.java b/apex/media/framework/java/android/media/BufferingParams.java
deleted file mode 100644
index 04af028..0000000
--- a/apex/media/framework/java/android/media/BufferingParams.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Structure for source buffering management params.
- *
- * Used by {@link MediaPlayer#getBufferingParams()} and
- * {@link MediaPlayer#setBufferingParams(BufferingParams)}
- * to control source buffering behavior.
- *
- * <p>There are two stages of source buffering in {@link MediaPlayer}: initial buffering
- * (when {@link MediaPlayer} is being prepared) and rebuffering (when {@link MediaPlayer}
- * is playing back source). {@link BufferingParams} includes corresponding marks for each
- * stage of source buffering. The marks are time based (in milliseconds).
- *
- * <p>{@link MediaPlayer} source component has default marks which can be queried by
- * calling {@link MediaPlayer#getBufferingParams()} before any change is made by
- * {@link MediaPlayer#setBufferingParams()}.
- * <ul>
- * <li><strong>initial buffering:</strong> initialMarkMs is used when
- * {@link MediaPlayer} is being prepared. When cached data amount exceeds this mark
- * {@link MediaPlayer} is prepared. </li>
- * <li><strong>rebuffering during playback:</strong> resumePlaybackMarkMs is used when
- * {@link MediaPlayer} is playing back content.
- * <ul>
- * <li> {@link MediaPlayer} has internal mark, namely pausePlaybackMarkMs, to decide when
- * to pause playback if cached data amount runs low. This internal mark varies based on
- * type of data source. </li>
- * <li> When cached data amount exceeds resumePlaybackMarkMs, {@link MediaPlayer} will
- * resume playback if it has been paused due to low cached data amount. The internal mark
- * pausePlaybackMarkMs shall be less than resumePlaybackMarkMs. </li>
- * <li> {@link MediaPlayer} has internal mark, namely pauseRebufferingMarkMs, to decide
- * when to pause rebuffering. Apparently, this internal mark shall be no less than
- * resumePlaybackMarkMs. </li>
- * <li> {@link MediaPlayer} has internal mark, namely resumeRebufferingMarkMs, to decide
- * when to resume buffering. This internal mark varies based on type of data source. This
- * mark shall be larger than pausePlaybackMarkMs, and less than pauseRebufferingMarkMs.
- * </li>
- * </ul> </li>
- * </ul>
- * <p>Users should use {@link Builder} to change {@link BufferingParams}.
- * @hide
- */
-public final class BufferingParams implements Parcelable {
- private static final int BUFFERING_NO_MARK = -1;
-
- // params
- private int mInitialMarkMs = BUFFERING_NO_MARK;
-
- private int mResumePlaybackMarkMs = BUFFERING_NO_MARK;
-
- private BufferingParams() {
- }
-
- /**
- * Return initial buffering mark in milliseconds.
- * @return initial buffering mark in milliseconds
- */
- public int getInitialMarkMs() {
- return mInitialMarkMs;
- }
-
- /**
- * Return the mark in milliseconds for resuming playback.
- * @return the mark for resuming playback in milliseconds
- */
- public int getResumePlaybackMarkMs() {
- return mResumePlaybackMarkMs;
- }
-
- /**
- * Builder class for {@link BufferingParams} objects.
- * <p> Here is an example where <code>Builder</code> is used to define the
- * {@link BufferingParams} to be used by a {@link MediaPlayer} instance:
- *
- * <pre class="prettyprint">
- * BufferingParams myParams = mediaplayer.getDefaultBufferingParams();
- * myParams = new BufferingParams.Builder(myParams)
- * .setInitialMarkMs(10000)
- * .setResumePlaybackMarkMs(15000)
- * .build();
- * mediaplayer.setBufferingParams(myParams);
- * </pre>
- */
- public static class Builder {
- private int mInitialMarkMs = BUFFERING_NO_MARK;
- private int mResumePlaybackMarkMs = BUFFERING_NO_MARK;
-
- /**
- * Constructs a new Builder with the defaults.
- * By default, all marks are -1.
- */
- public Builder() {
- }
-
- /**
- * Constructs a new Builder from a given {@link BufferingParams} instance
- * @param bp the {@link BufferingParams} object whose data will be reused
- * in the new Builder.
- */
- public Builder(BufferingParams bp) {
- mInitialMarkMs = bp.mInitialMarkMs;
- mResumePlaybackMarkMs = bp.mResumePlaybackMarkMs;
- }
-
- /**
- * Combines all of the fields that have been set and return a new
- * {@link BufferingParams} object. <code>IllegalStateException</code> will be
- * thrown if there is conflict between fields.
- * @return a new {@link BufferingParams} object
- */
- public BufferingParams build() {
- BufferingParams bp = new BufferingParams();
- bp.mInitialMarkMs = mInitialMarkMs;
- bp.mResumePlaybackMarkMs = mResumePlaybackMarkMs;
-
- return bp;
- }
-
- /**
- * Sets the time based mark in milliseconds for initial buffering.
- * @param markMs time based mark in milliseconds
- * @return the same Builder instance.
- */
- public Builder setInitialMarkMs(int markMs) {
- mInitialMarkMs = markMs;
- return this;
- }
-
- /**
- * Sets the time based mark in milliseconds for resuming playback.
- * @param markMs time based mark in milliseconds for resuming playback
- * @return the same Builder instance.
- */
- public Builder setResumePlaybackMarkMs(int markMs) {
- mResumePlaybackMarkMs = markMs;
- return this;
- }
- }
-
- private BufferingParams(Parcel in) {
- mInitialMarkMs = in.readInt();
- mResumePlaybackMarkMs = in.readInt();
- }
-
- public static final @android.annotation.NonNull Parcelable.Creator<BufferingParams> CREATOR =
- new Parcelable.Creator<BufferingParams>() {
- @Override
- public BufferingParams createFromParcel(Parcel in) {
- return new BufferingParams(in);
- }
-
- @Override
- public BufferingParams[] newArray(int size) {
- return new BufferingParams[size];
- }
- };
-
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mInitialMarkMs);
- dest.writeInt(mResumePlaybackMarkMs);
- }
-}
diff --git a/apex/media/framework/java/android/media/Controller2Link.java b/apex/media/framework/java/android/media/Controller2Link.java
deleted file mode 100644
index 8eefec7..0000000
--- a/apex/media/framework/java/android/media/Controller2Link.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-
-import java.util.Objects;
-
-/**
- * Handles incoming commands from {@link MediaSession2} to {@link MediaController2}.
- * @hide
- */
-// @SystemApi
-public final class Controller2Link implements Parcelable {
- private static final String TAG = "Controller2Link";
- private static final boolean DEBUG = MediaController2.DEBUG;
-
- public static final @android.annotation.NonNull Parcelable.Creator<Controller2Link> CREATOR =
- new Parcelable.Creator<Controller2Link>() {
- @Override
- public Controller2Link createFromParcel(Parcel in) {
- return new Controller2Link(in);
- }
-
- @Override
- public Controller2Link[] newArray(int size) {
- return new Controller2Link[size];
- }
- };
-
-
- private final MediaController2 mController;
- private final IMediaController2 mIController;
-
- public Controller2Link(MediaController2 controller) {
- mController = controller;
- mIController = new Controller2Stub();
- }
-
- Controller2Link(Parcel in) {
- mController = null;
- mIController = IMediaController2.Stub.asInterface(in.readStrongBinder());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mIController.asBinder());
- }
-
- @Override
- public int hashCode() {
- return mIController.asBinder().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Controller2Link)) {
- return false;
- }
- Controller2Link other = (Controller2Link) obj;
- return Objects.equals(mIController.asBinder(), other.mIController.asBinder());
- }
-
- /** Interface method for IMediaController2.notifyConnected */
- public void notifyConnected(int seq, Bundle connectionResult) {
- try {
- mIController.notifyConnected(seq, connectionResult);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Interface method for IMediaController2.notifyDisonnected */
- public void notifyDisconnected(int seq) {
- try {
- mIController.notifyDisconnected(seq);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Interface method for IMediaController2.notifyPlaybackActiveChanged */
- public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) {
- try {
- mIController.notifyPlaybackActiveChanged(seq, playbackActive);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Interface method for IMediaController2.sendSessionCommand */
- public void sendSessionCommand(int seq, Session2Command command, Bundle args,
- ResultReceiver resultReceiver) {
- try {
- mIController.sendSessionCommand(seq, command, args, resultReceiver);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Interface method for IMediaController2.cancelSessionCommand */
- public void cancelSessionCommand(int seq) {
- try {
- mIController.cancelSessionCommand(seq);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Stub implementation for IMediaController2.notifyConnected */
- public void onConnected(int seq, Bundle connectionResult) {
- if (connectionResult == null) {
- onDisconnected(seq);
- return;
- }
- mController.onConnected(seq, connectionResult);
- }
-
- /** Stub implementation for IMediaController2.notifyDisonnected */
- public void onDisconnected(int seq) {
- mController.onDisconnected(seq);
- }
-
- /** Stub implementation for IMediaController2.notifyPlaybackActiveChanged */
- public void onPlaybackActiveChanged(int seq, boolean playbackActive) {
- mController.onPlaybackActiveChanged(seq, playbackActive);
- }
-
- /** Stub implementation for IMediaController2.sendSessionCommand */
- public void onSessionCommand(int seq, Session2Command command, Bundle args,
- ResultReceiver resultReceiver) {
- mController.onSessionCommand(seq, command, args, resultReceiver);
- }
-
- /** Stub implementation for IMediaController2.cancelSessionCommand */
- public void onCancelCommand(int seq) {
- mController.onCancelCommand(seq);
- }
-
- private class Controller2Stub extends IMediaController2.Stub {
- @Override
- public void notifyConnected(int seq, Bundle connectionResult) {
- final long token = Binder.clearCallingIdentity();
- try {
- Controller2Link.this.onConnected(seq, connectionResult);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void notifyDisconnected(int seq) {
- final long token = Binder.clearCallingIdentity();
- try {
- Controller2Link.this.onDisconnected(seq);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) {
- final long token = Binder.clearCallingIdentity();
- try {
- Controller2Link.this.onPlaybackActiveChanged(seq, playbackActive);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void sendSessionCommand(int seq, Session2Command command, Bundle args,
- ResultReceiver resultReceiver) {
- final long token = Binder.clearCallingIdentity();
- try {
- Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void cancelSessionCommand(int seq) {
- final long token = Binder.clearCallingIdentity();
- try {
- Controller2Link.this.onCancelCommand(seq);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/DataSourceCallback.java b/apex/media/framework/java/android/media/DataSourceCallback.java
deleted file mode 100644
index c297ecd..0000000
--- a/apex/media/framework/java/android/media/DataSourceCallback.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package android.media;
-
-import android.annotation.NonNull;
-
-import java.io.Closeable;
-import java.io.IOException;
-
-/**
- * For supplying media data to the framework. Implement this if your app has
- * special requirements for the way media data is obtained.
- *
- * <p class="note">Methods of this interface may be called on multiple different
- * threads. There will be a thread synchronization point between each call to ensure that
- * modifications to the state of your DataSourceCallback are visible to future calls. This means
- * you don't need to do your own synchronization unless you're modifying the
- * DataSourceCallback from another thread while it's being used by the framework.</p>
- *
- * @hide
- */
-public abstract class DataSourceCallback implements Closeable {
-
- public static final int END_OF_STREAM = -1;
-
- /**
- * Called to request data from the given position.
- *
- * Implementations should should write up to {@code size} bytes into
- * {@code buffer}, and return the number of bytes written.
- *
- * Return {@code 0} if size is zero (thus no bytes are read).
- *
- * Return {@code -1} to indicate that end of stream is reached.
- *
- * @param position the position in the data source to read from.
- * @param buffer the buffer to read the data into.
- * @param offset the offset within buffer to read the data into.
- * @param size the number of bytes to read.
- * @throws IOException on fatal errors.
- * @return the number of bytes read, or {@link #END_OF_STREAM} if end of stream is reached.
- */
- public abstract int readAt(long position, @NonNull byte[] buffer, int offset, int size)
- throws IOException;
-
- /**
- * Called to get the size of the data source.
- *
- * @throws IOException on fatal errors
- * @return the size of data source in bytes, or -1 if the size is unknown.
- */
- public abstract long getSize() throws IOException;
-}
diff --git a/apex/media/framework/java/android/media/MediaCommunicationManager.java b/apex/media/framework/java/android/media/MediaCommunicationManager.java
deleted file mode 100644
index f39bcfb..0000000
--- a/apex/media/framework/java/android/media/MediaCommunicationManager.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-import static android.Manifest.permission.MEDIA_CONTENT_CONTROL;
-import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
-import android.annotation.SystemApi;
-import android.annotation.SystemService;
-import android.content.Context;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-import android.os.Build;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.service.media.MediaBrowserService;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.modules.annotation.MinSdk;
-import com.android.modules.utils.build.SdkLevel;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Executor;
-
-/**
- * Provides support for interacting with {@link android.media.MediaSession2 MediaSession2s}
- * that applications have published to express their ongoing media playback state.
- */
-@MinSdk(Build.VERSION_CODES.S)
-@SystemService(Context.MEDIA_COMMUNICATION_SERVICE)
-public class MediaCommunicationManager {
- private static final String TAG = "MediaCommunicationManager";
-
- /**
- * The manager version used from beginning.
- */
- private static final int VERSION_1 = 1;
-
- /**
- * Current manager version.
- */
- private static final int CURRENT_VERSION = VERSION_1;
-
- private final Context mContext;
- private final IMediaCommunicationService mService;
-
- private final Object mLock = new Object();
- private final CopyOnWriteArrayList<SessionCallbackRecord> mTokenCallbackRecords =
- new CopyOnWriteArrayList<>();
-
- @GuardedBy("mLock")
- private MediaCommunicationServiceCallbackStub mCallbackStub;
-
- /**
- * @hide
- */
- public MediaCommunicationManager(@NonNull Context context) {
- if (!SdkLevel.isAtLeastS()) {
- throw new UnsupportedOperationException("Android version must be S or greater.");
- }
- mContext = context;
- mService = IMediaCommunicationService.Stub.asInterface(
- MediaFrameworkInitializer.getMediaServiceManager()
- .getMediaCommunicationServiceRegisterer()
- .get());
- }
-
- /**
- * Gets the version of this {@link MediaCommunicationManager}.
- */
- public @IntRange(from = 1) int getVersion() {
- return CURRENT_VERSION;
- }
-
- /**
- * Notifies that a new {@link MediaSession2} with type {@link Session2Token#TYPE_SESSION} is
- * created.
- * @param token newly created session2 token
- * @hide
- */
- public void notifySession2Created(@NonNull Session2Token token) {
- Objects.requireNonNull(token, "token shouldn't be null");
- if (token.getType() != Session2Token.TYPE_SESSION) {
- throw new IllegalArgumentException("token's type should be TYPE_SESSION");
- }
- try {
- mService.notifySession2Created(token);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Checks whether the remote user is a trusted app.
- * <p>
- * An app is trusted if the app holds the
- * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission or has an enabled
- * notification listener.
- *
- * @param userInfo The remote user info from either
- * {@link MediaSession#getCurrentControllerInfo()} or
- * {@link MediaBrowserService#getCurrentBrowserInfo()}.
- * @return {@code true} if the remote user is trusted or {@code false} otherwise.
- * @hide
- */
- public boolean isTrustedForMediaControl(@NonNull MediaSessionManager.RemoteUserInfo userInfo) {
- Objects.requireNonNull(userInfo, "userInfo shouldn't be null");
- if (userInfo.getPackageName() == null) {
- return false;
- }
- try {
- return mService.isTrusted(
- userInfo.getPackageName(), userInfo.getPid(), userInfo.getUid());
- } catch (RemoteException e) {
- Log.w(TAG, "Cannot communicate with the service.", e);
- }
- return false;
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
- * current user.
- * <p>
- * Although this API can be used without any restriction, each session owners can accept or
- * reject your uses of {@link MediaSession2}.
- *
- * @return A list of {@link Session2Token}.
- */
- @NonNull
- public List<Session2Token> getSession2Tokens() {
- return getSession2Tokens(UserHandle.myUserId());
- }
-
- /**
- * Adds a callback to be notified when the list of active sessions changes.
- * <p>
- * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
- * held by the calling app.
- * </p>
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- @RequiresPermission(MEDIA_CONTENT_CONTROL)
- public void registerSessionCallback(@CallbackExecutor @NonNull Executor executor,
- @NonNull SessionCallback callback) {
- Objects.requireNonNull(executor, "executor must not be null");
- Objects.requireNonNull(callback, "callback must not be null");
-
- if (!mTokenCallbackRecords.addIfAbsent(
- new SessionCallbackRecord(executor, callback))) {
- Log.w(TAG, "registerSession2TokenCallback: Ignoring the same callback");
- return;
- }
- synchronized (mLock) {
- if (mCallbackStub == null) {
- MediaCommunicationServiceCallbackStub callbackStub =
- new MediaCommunicationServiceCallbackStub();
- try {
- mService.registerCallback(callbackStub, mContext.getPackageName());
- mCallbackStub = callbackStub;
- } catch (RemoteException ex) {
- Log.e(TAG, "Failed to register callback.", ex);
- }
- }
- }
- }
-
- /**
- * Stops receiving active sessions updates on the specified callback.
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public void unregisterSessionCallback(@NonNull SessionCallback callback) {
- if (!mTokenCallbackRecords.remove(
- new SessionCallbackRecord(null, callback))) {
- Log.w(TAG, "unregisterSession2TokenCallback: Ignoring an unknown callback.");
- return;
- }
- synchronized (mLock) {
- if (mCallbackStub != null && mTokenCallbackRecords.isEmpty()) {
- try {
- mService.unregisterCallback(mCallbackStub);
- } catch (RemoteException ex) {
- Log.e(TAG, "Failed to unregister callback.", ex);
- }
- mCallbackStub = null;
- }
- }
- }
-
- private List<Session2Token> getSession2Tokens(int userId) {
- try {
- MediaParceledListSlice slice = mService.getSession2Tokens(userId);
- return slice == null ? Collections.emptyList() : slice.getList();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to get session tokens", e);
- }
- return Collections.emptyList();
- }
-
- /**
- * Callback for listening to changes to the sessions.
- * @see #registerSessionCallback(Executor, SessionCallback)
- * @hide
- */
- @SystemApi(client = MODULE_LIBRARIES)
- public interface SessionCallback {
- /**
- * Called when a new {@link MediaSession2 media session2} is created.
- * @param token the newly created token
- */
- default void onSession2TokenCreated(@NonNull Session2Token token) {}
-
- /**
- * Called when {@link #getSession2Tokens() session tokens} are changed.
- */
- default void onSession2TokensChanged(@NonNull List<Session2Token> tokens) {}
- }
-
- private static final class SessionCallbackRecord {
- public final Executor executor;
- public final SessionCallback callback;
-
- SessionCallbackRecord(Executor executor, SessionCallback callback) {
- this.executor = executor;
- this.callback = callback;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(callback);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof SessionCallbackRecord)) {
- return false;
- }
- return Objects.equals(this.callback, ((SessionCallbackRecord) obj).callback);
- }
- }
-
- class MediaCommunicationServiceCallbackStub extends IMediaCommunicationServiceCallback.Stub {
- @Override
- public void onSession2Created(Session2Token token) throws RemoteException {
- for (SessionCallbackRecord record : mTokenCallbackRecords) {
- record.executor.execute(() -> record.callback.onSession2TokenCreated(token));
- }
- }
-
- @Override
- public void onSession2Changed(MediaParceledListSlice tokens) throws RemoteException {
- List<Session2Token> tokenList = tokens.getList();
- for (SessionCallbackRecord record : mTokenCallbackRecords) {
- record.executor.execute(() -> record.callback.onSession2TokensChanged(tokenList));
- }
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaConstants.java b/apex/media/framework/java/android/media/MediaConstants.java
deleted file mode 100644
index ce10889..0000000
--- a/apex/media/framework/java/android/media/MediaConstants.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-class MediaConstants {
- // Bundle key for int
- static final String KEY_PID = "android.media.key.PID";
-
- // Bundle key for String
- static final String KEY_PACKAGE_NAME = "android.media.key.PACKAGE_NAME";
-
- // Bundle key for Parcelable
- static final String KEY_SESSION2LINK = "android.media.key.SESSION2LINK";
- static final String KEY_ALLOWED_COMMANDS = "android.media.key.ALLOWED_COMMANDS";
- static final String KEY_PLAYBACK_ACTIVE = "android.media.key.PLAYBACK_ACTIVE";
- static final String KEY_TOKEN_EXTRAS = "android.media.key.TOKEN_EXTRAS";
- static final String KEY_CONNECTION_HINTS = "android.media.key.CONNECTION_HINTS";
-
- private MediaConstants() {
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaController2.java b/apex/media/framework/java/android/media/MediaController2.java
deleted file mode 100644
index 159e8e5..0000000
--- a/apex/media/framework/java/android/media/MediaController2.java
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
-import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
-import static android.media.MediaConstants.KEY_PACKAGE_NAME;
-import static android.media.MediaConstants.KEY_PID;
-import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
-import static android.media.MediaConstants.KEY_SESSION2LINK;
-import static android.media.MediaConstants.KEY_TOKEN_EXTRAS;
-import static android.media.Session2Command.Result.RESULT_ERROR_UNKNOWN_ERROR;
-import static android.media.Session2Command.Result.RESULT_INFO_SKIPPED;
-import static android.media.Session2Token.TYPE_SESSION;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import java.util.concurrent.Executor;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- *
- * Allows an app to interact with an active {@link MediaSession2} or a
- * {@link MediaSession2Service} which would provide {@link MediaSession2}. Media buttons and other
- * commands can be sent to the session.
- */
-public class MediaController2 implements AutoCloseable {
- static final String TAG = "MediaController2";
- static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final ControllerCallback mCallback;
-
- private final IBinder.DeathRecipient mDeathRecipient = () -> close();
- private final Context mContext;
- private final Session2Token mSessionToken;
- private final Executor mCallbackExecutor;
- private final Controller2Link mControllerStub;
- private final Handler mResultHandler;
- private final SessionServiceConnection mServiceConnection;
-
- private final Object mLock = new Object();
- //@GuardedBy("mLock")
- private boolean mClosed;
- //@GuardedBy("mLock")
- private int mNextSeqNumber;
- //@GuardedBy("mLock")
- private Session2Link mSessionBinder;
- //@GuardedBy("mLock")
- private Session2CommandGroup mAllowedCommands;
- //@GuardedBy("mLock")
- private Session2Token mConnectedToken;
- //@GuardedBy("mLock")
- private ArrayMap<ResultReceiver, Integer> mPendingCommands;
- //@GuardedBy("mLock")
- private ArraySet<Integer> mRequestedCommandSeqNumbers;
- //@GuardedBy("mLock")
- private boolean mPlaybackActive;
-
- /**
- * Create a {@link MediaController2} from the {@link Session2Token}.
- * This connects to the session and may wake up the service if it's not available.
- *
- * @param context context
- * @param token token to connect to
- * @param connectionHints a session-specific argument to send to the session when connecting.
- * The contents of this bundle may affect the connection result.
- * @param executor executor to run callbacks on.
- * @param callback controller callback to receive changes in.
- */
- MediaController2(@NonNull Context context, @NonNull Session2Token token,
- @NonNull Bundle connectionHints, @NonNull Executor executor,
- @NonNull ControllerCallback callback) {
- if (context == null) {
- throw new IllegalArgumentException("context shouldn't be null");
- }
- if (token == null) {
- throw new IllegalArgumentException("token shouldn't be null");
- }
- mContext = context;
- mSessionToken = token;
- mCallbackExecutor = (executor == null) ? context.getMainExecutor() : executor;
- mCallback = (callback == null) ? new ControllerCallback() {} : callback;
- mControllerStub = new Controller2Link(this);
- // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
- mResultHandler = new Handler(context.getMainLooper());
-
- mNextSeqNumber = 0;
- mPendingCommands = new ArrayMap<>();
- mRequestedCommandSeqNumbers = new ArraySet<>();
-
- boolean connectRequested;
- if (token.getType() == TYPE_SESSION) {
- mServiceConnection = null;
- connectRequested = requestConnectToSession(connectionHints);
- } else {
- mServiceConnection = new SessionServiceConnection(connectionHints);
- connectRequested = requestConnectToService();
- }
- if (!connectRequested) {
- close();
- }
- }
-
- @Override
- public void close() {
- synchronized (mLock) {
- if (mClosed) {
- // Already closed. Ignore rest of clean up code.
- // Note: unbindService() throws IllegalArgumentException when it's called twice.
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "closing " + this);
- }
- mClosed = true;
- if (mServiceConnection != null) {
- // Note: This should be called even when the bindService() has returned false.
- mContext.unbindService(mServiceConnection);
- }
- if (mSessionBinder != null) {
- try {
- mSessionBinder.disconnect(mControllerStub, getNextSeqNumber());
- mSessionBinder.unlinkToDeath(mDeathRecipient, 0);
- } catch (RuntimeException e) {
- // No-op
- }
- }
- mConnectedToken = null;
- mPendingCommands.clear();
- mRequestedCommandSeqNumbers.clear();
- mCallbackExecutor.execute(() -> {
- mCallback.onDisconnected(MediaController2.this);
- });
- mSessionBinder = null;
- }
- }
-
- /**
- * Returns {@link Session2Token} of the connected session.
- * If it is not connected yet, it returns {@code null}.
- * <p>
- * This may differ with the {@link Session2Token} from the constructor. For example, if the
- * controller is created with the token for {@link MediaSession2Service}, this would return
- * token for the {@link MediaSession2} in the service.
- *
- * @return Session2Token of the connected session, or {@code null} if not connected
- */
- @Nullable
- public Session2Token getConnectedToken() {
- synchronized (mLock) {
- return mConnectedToken;
- }
- }
-
- /**
- * Returns whether the session's playback is active.
- *
- * @return {@code true} if playback active. {@code false} otherwise.
- * @see ControllerCallback#onPlaybackActiveChanged(MediaController2, boolean)
- */
- public boolean isPlaybackActive() {
- synchronized (mLock) {
- return mPlaybackActive;
- }
- }
-
- /**
- * Sends a session command to the session
- * <p>
- * @param command the session command
- * @param args optional arguments
- * @return a token which will be sent together in {@link ControllerCallback#onCommandResult}
- * when its result is received.
- */
- @NonNull
- public Object sendSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) {
- if (command == null) {
- throw new IllegalArgumentException("command shouldn't be null");
- }
-
- ResultReceiver resultReceiver = new ResultReceiver(mResultHandler) {
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- synchronized (mLock) {
- mPendingCommands.remove(this);
- }
- mCallbackExecutor.execute(() -> {
- mCallback.onCommandResult(MediaController2.this, this,
- command, new Session2Command.Result(resultCode, resultData));
- });
- }
- };
-
- synchronized (mLock) {
- if (mSessionBinder != null) {
- int seq = getNextSeqNumber();
- mPendingCommands.put(resultReceiver, seq);
- try {
- mSessionBinder.sendSessionCommand(mControllerStub, seq, command, args,
- resultReceiver);
- } catch (RuntimeException e) {
- mPendingCommands.remove(resultReceiver);
- resultReceiver.send(RESULT_ERROR_UNKNOWN_ERROR, null);
- }
- }
- }
- return resultReceiver;
- }
-
- /**
- * Cancels the session command previously sent.
- *
- * @param token the token which is returned from {@link #sendSessionCommand}.
- */
- public void cancelSessionCommand(@NonNull Object token) {
- if (token == null) {
- throw new IllegalArgumentException("token shouldn't be null");
- }
- synchronized (mLock) {
- if (mSessionBinder == null) return;
- Integer seq = mPendingCommands.remove(token);
- if (seq != null) {
- mSessionBinder.cancelSessionCommand(mControllerStub, seq);
- }
- }
- }
-
- // Called by Controller2Link.onConnected
- void onConnected(int seq, Bundle connectionResult) {
- Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK);
- Session2CommandGroup allowedCommands =
- connectionResult.getParcelable(KEY_ALLOWED_COMMANDS);
- boolean playbackActive = connectionResult.getBoolean(KEY_PLAYBACK_ACTIVE);
-
- Bundle tokenExtras = connectionResult.getBundle(KEY_TOKEN_EXTRAS);
- if (tokenExtras == null) {
- Log.w(TAG, "extras shouldn't be null.");
- tokenExtras = Bundle.EMPTY;
- } else if (MediaSession2.hasCustomParcelable(tokenExtras)) {
- Log.w(TAG, "extras contain custom parcelable. Ignoring.");
- tokenExtras = Bundle.EMPTY;
- }
-
- if (DEBUG) {
- Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder
- + ", allowedCommands=" + allowedCommands);
- }
- if (sessionBinder == null || allowedCommands == null) {
- // Connection rejected.
- close();
- return;
- }
- synchronized (mLock) {
- mSessionBinder = sessionBinder;
- mAllowedCommands = allowedCommands;
- mPlaybackActive = playbackActive;
-
- // Implementation for the local binder is no-op,
- // so can be used without worrying about deadlock.
- sessionBinder.linkToDeath(mDeathRecipient, 0);
- mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION,
- mSessionToken.getPackageName(), sessionBinder, tokenExtras);
- }
- mCallbackExecutor.execute(() -> {
- mCallback.onConnected(MediaController2.this, allowedCommands);
- });
- }
-
- // Called by Controller2Link.onDisconnected
- void onDisconnected(int seq) {
- // close() will call mCallback.onDisconnected
- close();
- }
-
- // Called by Controller2Link.onPlaybackActiveChanged
- void onPlaybackActiveChanged(int seq, boolean playbackActive) {
- synchronized (mLock) {
- mPlaybackActive = playbackActive;
- }
- mCallbackExecutor.execute(() -> {
- mCallback.onPlaybackActiveChanged(MediaController2.this, playbackActive);
- });
- }
-
- // Called by Controller2Link.onSessionCommand
- void onSessionCommand(int seq, Session2Command command, Bundle args,
- @Nullable ResultReceiver resultReceiver) {
- synchronized (mLock) {
- mRequestedCommandSeqNumbers.add(seq);
- }
- mCallbackExecutor.execute(() -> {
- boolean isCanceled;
- synchronized (mLock) {
- isCanceled = !mRequestedCommandSeqNumbers.remove(seq);
- }
- if (isCanceled) {
- if (resultReceiver != null) {
- resultReceiver.send(RESULT_INFO_SKIPPED, null);
- }
- return;
- }
- Session2Command.Result result = mCallback.onSessionCommand(
- MediaController2.this, command, args);
- if (resultReceiver != null) {
- if (result == null) {
- resultReceiver.send(RESULT_INFO_SKIPPED, null);
- } else {
- resultReceiver.send(result.getResultCode(), result.getResultData());
- }
- }
- });
- }
-
- // Called by Controller2Link.onSessionCommand
- void onCancelCommand(int seq) {
- synchronized (mLock) {
- mRequestedCommandSeqNumbers.remove(seq);
- }
- }
-
- private int getNextSeqNumber() {
- synchronized (mLock) {
- return mNextSeqNumber++;
- }
- }
-
- private Bundle createConnectionRequest(@NonNull Bundle connectionHints) {
- Bundle connectionRequest = new Bundle();
- connectionRequest.putString(KEY_PACKAGE_NAME, mContext.getPackageName());
- connectionRequest.putInt(KEY_PID, Process.myPid());
- connectionRequest.putBundle(KEY_CONNECTION_HINTS, connectionHints);
- return connectionRequest;
- }
-
- private boolean requestConnectToSession(@NonNull Bundle connectionHints) {
- Session2Link sessionBinder = mSessionToken.getSessionLink();
- Bundle connectionRequest = createConnectionRequest(connectionHints);
- try {
- sessionBinder.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
- } catch (RuntimeException e) {
- Log.w(TAG, "Failed to call connection request", e);
- return false;
- }
- return true;
- }
-
- private boolean requestConnectToService() {
- // Service. Needs to get fresh binder whenever connection is needed.
- final Intent intent = new Intent(MediaSession2Service.SERVICE_INTERFACE);
- intent.setClassName(mSessionToken.getPackageName(), mSessionToken.getServiceName());
-
- // Use bindService() instead of startForegroundService() to start session service for three
- // reasons.
- // 1. Prevent session service owner's stopSelf() from destroying service.
- // With the startForegroundService(), service's call of stopSelf() will trigger immediate
- // onDestroy() calls on the main thread even when onConnect() is running in another
- // thread.
- // 2. Minimize APIs for developers to take care about.
- // With bindService(), developers only need to take care about Service.onBind()
- // but Service.onStartCommand() should be also taken care about with the
- // startForegroundService().
- // 3. Future support for UI-less playback
- // If a service wants to keep running, it should be either foreground service or
- // bound service. But there had been request for the feature for system apps
- // and using bindService() will be better fit with it.
- synchronized (mLock) {
- boolean result = mContext.bindService(
- intent, mServiceConnection, Context.BIND_AUTO_CREATE);
- if (!result) {
- Log.w(TAG, "bind to " + mSessionToken + " failed");
- return false;
- } else if (DEBUG) {
- Log.d(TAG, "bind to " + mSessionToken + " succeeded");
- }
- }
- return true;
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Builder for {@link MediaController2}.
- * <p>
- * Any incoming event from the {@link MediaSession2} will be handled on the callback
- * executor. If it's not set, {@link Context#getMainExecutor()} will be used by default.
- */
- public static final class Builder {
- private Context mContext;
- private Session2Token mToken;
- private Bundle mConnectionHints;
- private Executor mCallbackExecutor;
- private ControllerCallback mCallback;
-
- /**
- * Creates a builder for {@link MediaController2}.
- *
- * @param context context
- * @param token token of the session to connect to
- */
- public Builder(@NonNull Context context, @NonNull Session2Token token) {
- if (context == null) {
- throw new IllegalArgumentException("context shouldn't be null");
- }
- if (token == null) {
- throw new IllegalArgumentException("token shouldn't be null");
- }
- mContext = context;
- mToken = token;
- }
-
- /**
- * Set the connection hints for the controller.
- * <p>
- * {@code connectionHints} is a session-specific argument to send to the session when
- * connecting. The contents of this bundle may affect the connection result.
- * <p>
- * An {@link IllegalArgumentException} will be thrown if the bundle contains any
- * non-framework Parcelable objects.
- *
- * @param connectionHints a bundle which contains the connection hints
- * @return The Builder to allow chaining
- */
- @NonNull
- public Builder setConnectionHints(@NonNull Bundle connectionHints) {
- if (connectionHints == null) {
- throw new IllegalArgumentException("connectionHints shouldn't be null");
- }
- if (MediaSession2.hasCustomParcelable(connectionHints)) {
- throw new IllegalArgumentException("connectionHints shouldn't contain any custom "
- + "parcelables");
- }
- mConnectionHints = new Bundle(connectionHints);
- return this;
- }
-
- /**
- * Set callback for the controller and its executor.
- *
- * @param executor callback executor
- * @param callback session callback.
- * @return The Builder to allow chaining
- */
- @NonNull
- public Builder setControllerCallback(@NonNull Executor executor,
- @NonNull ControllerCallback callback) {
- if (executor == null) {
- throw new IllegalArgumentException("executor shouldn't be null");
- }
- if (callback == null) {
- throw new IllegalArgumentException("callback shouldn't be null");
- }
- mCallbackExecutor = executor;
- mCallback = callback;
- return this;
- }
-
- /**
- * Build {@link MediaController2}.
- *
- * @return a new controller
- */
- @NonNull
- public MediaController2 build() {
- if (mCallbackExecutor == null) {
- mCallbackExecutor = mContext.getMainExecutor();
- }
- if (mCallback == null) {
- mCallback = new ControllerCallback() {};
- }
- if (mConnectionHints == null) {
- mConnectionHints = Bundle.EMPTY;
- }
- return new MediaController2(
- mContext, mToken, mConnectionHints, mCallbackExecutor, mCallback);
- }
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Interface for listening to change in activeness of the {@link MediaSession2}.
- */
- public abstract static class ControllerCallback {
- /**
- * Called when the controller is successfully connected to the session. The controller
- * becomes available afterwards.
- *
- * @param controller the controller for this event
- * @param allowedCommands commands that's allowed by the session.
- */
- public void onConnected(@NonNull MediaController2 controller,
- @NonNull Session2CommandGroup allowedCommands) {}
-
- /**
- * Called when the session refuses the controller or the controller is disconnected from
- * the session. The controller becomes unavailable afterwards and the callback wouldn't
- * be called.
- * <p>
- * It will be also called after the {@link #close()}, so you can put clean up code here.
- * You don't need to call {@link #close()} after this.
- *
- * @param controller the controller for this event
- */
- public void onDisconnected(@NonNull MediaController2 controller) {}
-
- /**
- * Called when the session's playback activeness is changed.
- *
- * @param controller the controller for this event
- * @param playbackActive {@code true} if the session's playback is active.
- * {@code false} otherwise.
- * @see MediaController2#isPlaybackActive()
- */
- public void onPlaybackActiveChanged(@NonNull MediaController2 controller,
- boolean playbackActive) {}
-
- /**
- * Called when the connected session sent a session command.
- *
- * @param controller the controller for this event
- * @param command the session command
- * @param args optional arguments
- * @return the result for the session command. If {@code null}, RESULT_INFO_SKIPPED
- * will be sent to the session.
- */
- @Nullable
- public Session2Command.Result onSessionCommand(@NonNull MediaController2 controller,
- @NonNull Session2Command command, @Nullable Bundle args) {
- return null;
- }
-
- /**
- * Called when the command sent to the connected session is finished.
- *
- * @param controller the controller for this event
- * @param token the token got from {@link MediaController2#sendSessionCommand}
- * @param command the session command
- * @param result the result of the session command
- */
- public void onCommandResult(@NonNull MediaController2 controller, @NonNull Object token,
- @NonNull Session2Command command, @NonNull Session2Command.Result result) {}
- }
-
- // This will be called on the main thread.
- private class SessionServiceConnection implements ServiceConnection {
- private final Bundle mConnectionHints;
-
- SessionServiceConnection(@Nullable Bundle connectionHints) {
- mConnectionHints = connectionHints;
- }
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- // Note that it's always main-thread.
- boolean connectRequested = false;
- try {
- if (DEBUG) {
- Log.d(TAG, "onServiceConnected " + name + " " + this);
- }
- if (!mSessionToken.getPackageName().equals(name.getPackageName())) {
- Log.wtf(TAG, "Expected connection to " + mSessionToken.getPackageName()
- + " but is connected to " + name);
- return;
- }
- IMediaSession2Service iService = IMediaSession2Service.Stub.asInterface(service);
- if (iService == null) {
- Log.wtf(TAG, "Service interface is missing.");
- return;
- }
- Bundle connectionRequest = createConnectionRequest(mConnectionHints);
- iService.connect(mControllerStub, getNextSeqNumber(), connectionRequest);
- connectRequested = true;
- } catch (RemoteException e) {
- Log.w(TAG, "Service " + name + " has died prematurely", e);
- } finally {
- if (!connectRequested) {
- close();
- }
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // Temporal lose of the binding because of the service crash. System will automatically
- // rebind, so just no-op.
- if (DEBUG) {
- Log.w(TAG, "Session service " + name + " is disconnected.");
- }
- close();
- }
-
- @Override
- public void onBindingDied(ComponentName name) {
- // Permanent lose of the binding because of the service package update or removed.
- // This SessionServiceRecord will be removed accordingly, but forget session binder here
- // for sure.
- close();
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaFeature.java b/apex/media/framework/java/android/media/MediaFeature.java
deleted file mode 100644
index 8d1b159..0000000
--- a/apex/media/framework/java/android/media/MediaFeature.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.StringDef;
-import android.os.Build;
-
-import com.android.modules.annotation.MinSdk;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * MediaFeature defines various media features, e.g. hdr type.
- */
-@MinSdk(Build.VERSION_CODES.S)
-public final class MediaFeature {
- /**
- * Defines tye type of HDR(high dynamic range) video.
- */
- public static final class HdrType {
- private HdrType() {
- }
-
- /**
- * HDR type for dolby-vision.
- */
- public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
- /**
- * HDR type for hdr10.
- */
- public static final String HDR10 = "android.media.feature.hdr.hdr10";
- /**
- * HDR type for hdr10+.
- */
- public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
- /**
- * HDR type for hlg.
- */
- public static final String HLG = "android.media.feature.hdr.hlg";
- }
-
- /** @hide */
- @StringDef({
- HdrType.DOLBY_VISION,
- HdrType.HDR10,
- HdrType.HDR10_PLUS,
- HdrType.HLG,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface MediaHdrType {
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java
deleted file mode 100644
index 75a56b72..0000000
--- a/apex/media/framework/java/android/media/MediaFrameworkInitializer.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.annotation.SystemApi.Client;
-import android.app.SystemServiceRegistry;
-import android.content.Context;
-import android.os.Build;
-
-import com.android.modules.annotation.MinSdk;
-import com.android.modules.utils.build.SdkLevel;
-
-/**
- * Class for performing registration for all media services on com.android.media apex.
- *
- * @hide
- */
-@MinSdk(Build.VERSION_CODES.S)
-@SystemApi(client = Client.MODULE_LIBRARIES)
-public class MediaFrameworkInitializer {
- private MediaFrameworkInitializer() {
- }
-
- private static volatile MediaServiceManager sMediaServiceManager;
-
- /**
- * Sets an instance of {@link MediaServiceManager} that allows
- * the media mainline module to register/obtain media binder services. This is called
- * by the platform during the system initialization.
- *
- * @param mediaServiceManager instance of {@link MediaServiceManager} that allows
- * the media mainline module to register/obtain media binder services.
- */
- public static void setMediaServiceManager(
- @NonNull MediaServiceManager mediaServiceManager) {
- if (sMediaServiceManager != null) {
- throw new IllegalStateException("setMediaServiceManager called twice!");
- }
-
- if (mediaServiceManager == null) {
- throw new NullPointerException("mediaServiceManager is null!");
- }
-
- sMediaServiceManager = mediaServiceManager;
- }
-
- /** @hide */
- public static MediaServiceManager getMediaServiceManager() {
- return sMediaServiceManager;
- }
-
- /**
- * Called by {@link SystemServiceRegistry}'s static initializer and registers all media
- * services to {@link Context}, so that {@link Context#getSystemService} can return them.
- *
- * @throws IllegalStateException if this is called from anywhere besides
- * {@link SystemServiceRegistry}
- */
- public static void registerServiceWrappers() {
- SystemServiceRegistry.registerContextAwareService(
- Context.MEDIA_TRANSCODING_SERVICE,
- MediaTranscodingManager.class,
- context -> new MediaTranscodingManager(context)
- );
- if (SdkLevel.isAtLeastS()) {
- SystemServiceRegistry.registerContextAwareService(
- Context.MEDIA_COMMUNICATION_SERVICE,
- MediaCommunicationManager.class,
- context -> new MediaCommunicationManager(context)
- );
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaParceledListSlice.java b/apex/media/framework/java/android/media/MediaParceledListSlice.java
deleted file mode 100644
index 47ac193..0000000
--- a/apex/media/framework/java/android/media/MediaParceledListSlice.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.NonNull;
-import android.annotation.SystemApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * This is a copied version of MediaParceledListSlice in framework with hidden API usages removed,
- * and also with some lint error fixed.
- *
- * Transfer a large list of Parcelable objects across an IPC. Splits into
- * multiple transactions if needed.
- *
- * TODO: Remove this from @SystemApi once all the MediaSession related classes are moved
- * to apex (or ParceledListSlice moved to apex). This class is temporaily added to system API
- * for moving classes step by step.
- *
- * @param <T> The type of the elements in the list.
- * @see BaseMediaParceledListSlice
- * @deprecated This is temporary marked as @SystemApi. Should be removed from the API surface.
- * @hide
- */
-@Deprecated
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-public final class MediaParceledListSlice<T extends Parcelable>
- extends BaseMediaParceledListSlice<T> {
- public MediaParceledListSlice(@NonNull List<T> list) {
- super(list);
- }
-
- private MediaParceledListSlice(Parcel in, ClassLoader loader) {
- super(in, loader);
- }
-
- @NonNull
- public static <T extends Parcelable> MediaParceledListSlice<T> emptyList() {
- return new MediaParceledListSlice<T>(Collections.<T> emptyList());
- }
-
- @Override
- public int describeContents() {
- int contents = 0;
- final List<T> list = getList();
- for (int i=0; i<list.size(); i++) {
- contents |= list.get(i).describeContents();
- }
- return contents;
- }
-
- @Override
- void writeElement(T parcelable, Parcel dest, int callFlags) {
- parcelable.writeToParcel(dest, callFlags);
- }
-
- @Override
- void writeParcelableCreator(T parcelable, Parcel dest) {
- dest.writeParcelableCreator((Parcelable) parcelable);
- }
-
- @Override
- Parcelable.Creator<?> readParcelableCreator(Parcel from, ClassLoader loader) {
- return from.readParcelableCreator(loader);
- }
-
- @NonNull
- @SuppressWarnings("unchecked")
- public static final Parcelable.ClassLoaderCreator<MediaParceledListSlice> CREATOR =
- new Parcelable.ClassLoaderCreator<MediaParceledListSlice>() {
- public MediaParceledListSlice createFromParcel(Parcel in) {
- return new MediaParceledListSlice(in, null);
- }
-
- @Override
- public MediaParceledListSlice createFromParcel(Parcel in, ClassLoader loader) {
- return new MediaParceledListSlice(in, loader);
- }
-
- @Override
- public MediaParceledListSlice[] newArray(int size) {
- return new MediaParceledListSlice[size];
- }
- };
-}
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
deleted file mode 100644
index 8cc3bc0..0000000
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ /dev/null
@@ -1,2292 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringDef;
-import android.media.MediaCodec.CryptoInfo;
-import android.media.metrics.LogSessionId;
-import android.os.Build;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.Pair;
-import android.util.SparseArray;
-
-import androidx.annotation.RequiresApi;
-
-import com.android.modules.utils.build.SdkLevel;
-
-import com.google.android.exoplayer2.C;
-import com.google.android.exoplayer2.Format;
-import com.google.android.exoplayer2.ParserException;
-import com.google.android.exoplayer2.drm.DrmInitData.SchemeData;
-import com.google.android.exoplayer2.extractor.ChunkIndex;
-import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
-import com.google.android.exoplayer2.extractor.Extractor;
-import com.google.android.exoplayer2.extractor.ExtractorInput;
-import com.google.android.exoplayer2.extractor.ExtractorOutput;
-import com.google.android.exoplayer2.extractor.PositionHolder;
-import com.google.android.exoplayer2.extractor.SeekMap.SeekPoints;
-import com.google.android.exoplayer2.extractor.TrackOutput;
-import com.google.android.exoplayer2.extractor.amr.AmrExtractor;
-import com.google.android.exoplayer2.extractor.flac.FlacExtractor;
-import com.google.android.exoplayer2.extractor.flv.FlvExtractor;
-import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor;
-import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
-import com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor;
-import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
-import com.google.android.exoplayer2.extractor.ogg.OggExtractor;
-import com.google.android.exoplayer2.extractor.ts.Ac3Extractor;
-import com.google.android.exoplayer2.extractor.ts.Ac4Extractor;
-import com.google.android.exoplayer2.extractor.ts.AdtsExtractor;
-import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory;
-import com.google.android.exoplayer2.extractor.ts.PsExtractor;
-import com.google.android.exoplayer2.extractor.ts.TsExtractor;
-import com.google.android.exoplayer2.extractor.wav.WavExtractor;
-import com.google.android.exoplayer2.upstream.DataReader;
-import com.google.android.exoplayer2.util.ParsableByteArray;
-import com.google.android.exoplayer2.util.TimestampAdjuster;
-import com.google.android.exoplayer2.util.Util;
-import com.google.android.exoplayer2.video.ColorInfo;
-
-import java.io.EOFException;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.function.Function;
-
-/**
- * Parses media container formats and extracts contained media samples and metadata.
- *
- * <p>This class provides access to a battery of low-level media container parsers. Each instance of
- * this class is associated to a specific media parser implementation which is suitable for
- * extraction from a specific media container format. The media parser implementation assignment
- * depends on the factory method (see {@link #create} and {@link #createByName}) used to create the
- * instance.
- *
- * <p>Users must implement the following to use this class.
- *
- * <ul>
- * <li>{@link InputReader}: Provides the media container's bytes to parse.
- * <li>{@link OutputConsumer}: Provides a sink for all extracted data and metadata.
- * </ul>
- *
- * <p>The following code snippet includes a usage example:
- *
- * <pre>
- * MyOutputConsumer myOutputConsumer = new MyOutputConsumer();
- * MyInputReader myInputReader = new MyInputReader("www.example.com");
- * MediaParser mediaParser = MediaParser.create(myOutputConsumer);
- *
- * while (mediaParser.advance(myInputReader)) {}
- *
- * mediaParser.release();
- * mediaParser = null;
- * </pre>
- *
- * <p>The following code snippet provides a rudimentary {@link OutputConsumer} sample implementation
- * which extracts and publishes all video samples:
- *
- * <pre>
- * class VideoOutputConsumer implements MediaParser.OutputConsumer {
- *
- * private byte[] sampleDataBuffer = new byte[4096];
- * private byte[] discardedDataBuffer = new byte[4096];
- * private int videoTrackIndex = -1;
- * private int bytesWrittenCount = 0;
- *
- * @Override
- * public void onSeekMapFound(int i, @NonNull MediaFormat mediaFormat) {
- * // Do nothing.
- * }
- *
- * @Override
- * public void onTrackDataFound(int i, @NonNull TrackData trackData) {
- * MediaFormat mediaFormat = trackData.mediaFormat;
- * if (videoTrackIndex == -1 &&
- * mediaFormat
- * .getString(MediaFormat.KEY_MIME, /* defaultValue= */ "")
- * .startsWith("video/")) {
- * videoTrackIndex = i;
- * }
- * }
- *
- * @Override
- * public void onSampleDataFound(int trackIndex, @NonNull InputReader inputReader)
- * throws IOException {
- * int numberOfBytesToRead = (int) inputReader.getLength();
- * if (videoTrackIndex != trackIndex) {
- * // Discard contents.
- * inputReader.read(
- * discardedDataBuffer,
- * /* offset= */ 0,
- * Math.min(discardDataBuffer.length, numberOfBytesToRead));
- * } else {
- * ensureSpaceInBuffer(numberOfBytesToRead);
- * int bytesRead = inputReader.read(
- * sampleDataBuffer, bytesWrittenCount, numberOfBytesToRead);
- * bytesWrittenCount += bytesRead;
- * }
- * }
- *
- * @Override
- * public void onSampleCompleted(
- * int trackIndex,
- * long timeMicros,
- * int flags,
- * int size,
- * int offset,
- * @Nullable CryptoInfo cryptoData) {
- * if (videoTrackIndex != trackIndex) {
- * return; // It's not the video track. Ignore.
- * }
- * byte[] sampleData = new byte[size];
- * int sampleStartOffset = bytesWrittenCount - size - offset;
- * System.arraycopy(
- * sampleDataBuffer,
- * sampleStartOffset,
- * sampleData,
- * /* destPos= */ 0,
- * size);
- * // Place trailing bytes at the start of the buffer.
- * System.arraycopy(
- * sampleDataBuffer,
- * bytesWrittenCount - offset,
- * sampleDataBuffer,
- * /* destPos= */ 0,
- * /* size= */ offset);
- * bytesWrittenCount = bytesWrittenCount - offset;
- * publishSample(sampleData, timeMicros, flags);
- * }
- *
- * private void ensureSpaceInBuffer(int numberOfBytesToRead) {
- * int requiredLength = bytesWrittenCount + numberOfBytesToRead;
- * if (requiredLength > sampleDataBuffer.length) {
- * sampleDataBuffer = Arrays.copyOf(sampleDataBuffer, requiredLength);
- * }
- * }
- *
- * }
- *
- * </pre>
- */
-public final class MediaParser {
-
- /**
- * Maps seek positions to {@link SeekPoint SeekPoints} in the stream.
- *
- * <p>A {@link SeekPoint} is a position in the stream from which a player may successfully start
- * playing media samples.
- */
- public static final class SeekMap {
-
- /** Returned by {@link #getDurationMicros()} when the duration is unknown. */
- public static final int UNKNOWN_DURATION = Integer.MIN_VALUE;
-
- /**
- * For each {@link #getSeekPoints} call, returns a single {@link SeekPoint} whose {@link
- * SeekPoint#timeMicros} matches the requested timestamp, and whose {@link
- * SeekPoint#position} is 0.
- *
- * @hide
- */
- public static final SeekMap DUMMY = new SeekMap(new DummyExoPlayerSeekMap());
-
- private final com.google.android.exoplayer2.extractor.SeekMap mExoPlayerSeekMap;
-
- private SeekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
- mExoPlayerSeekMap = exoplayerSeekMap;
- }
-
- /** Returns whether seeking is supported. */
- public boolean isSeekable() {
- return mExoPlayerSeekMap.isSeekable();
- }
-
- /**
- * Returns the duration of the stream in microseconds or {@link #UNKNOWN_DURATION} if the
- * duration is unknown.
- */
- public long getDurationMicros() {
- long durationUs = mExoPlayerSeekMap.getDurationUs();
- return durationUs != C.TIME_UNSET ? durationUs : UNKNOWN_DURATION;
- }
-
- /**
- * Obtains {@link SeekPoint SeekPoints} for the specified seek time in microseconds.
- *
- * <p>{@code getSeekPoints(timeMicros).first} contains the latest seek point for samples
- * with timestamp equal to or smaller than {@code timeMicros}.
- *
- * <p>{@code getSeekPoints(timeMicros).second} contains the earliest seek point for samples
- * with timestamp equal to or greater than {@code timeMicros}. If a seek point exists for
- * {@code timeMicros}, the returned pair will contain the same {@link SeekPoint} twice.
- *
- * @param timeMicros A seek time in microseconds.
- * @return The corresponding {@link SeekPoint SeekPoints}.
- */
- @NonNull
- public Pair<SeekPoint, SeekPoint> getSeekPoints(long timeMicros) {
- SeekPoints seekPoints = mExoPlayerSeekMap.getSeekPoints(timeMicros);
- return new Pair<>(toSeekPoint(seekPoints.first), toSeekPoint(seekPoints.second));
- }
- }
-
- /** Holds information associated with a track. */
- public static final class TrackData {
-
- /** Holds {@link MediaFormat} information for the track. */
- @NonNull public final MediaFormat mediaFormat;
-
- /**
- * Holds {@link DrmInitData} necessary to acquire keys associated with the track, or null if
- * the track has no encryption data.
- */
- @Nullable public final DrmInitData drmInitData;
-
- private TrackData(MediaFormat mediaFormat, DrmInitData drmInitData) {
- this.mediaFormat = mediaFormat;
- this.drmInitData = drmInitData;
- }
- }
-
- /** Defines a seek point in a media stream. */
- public static final class SeekPoint {
-
- /** A {@link SeekPoint} whose time and byte offset are both set to 0. */
- @NonNull public static final SeekPoint START = new SeekPoint(0, 0);
-
- /** The time of the seek point, in microseconds. */
- public final long timeMicros;
-
- /** The byte offset of the seek point. */
- public final long position;
-
- /**
- * @param timeMicros The time of the seek point, in microseconds.
- * @param position The byte offset of the seek point.
- */
- private SeekPoint(long timeMicros, long position) {
- this.timeMicros = timeMicros;
- this.position = position;
- }
-
- @Override
- @NonNull
- public String toString() {
- return "[timeMicros=" + timeMicros + ", position=" + position + "]";
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
- SeekPoint other = (SeekPoint) obj;
- return timeMicros == other.timeMicros && position == other.position;
- }
-
- @Override
- public int hashCode() {
- int result = (int) timeMicros;
- result = 31 * result + (int) position;
- return result;
- }
- }
-
- /** Provides input data to {@link MediaParser}. */
- public interface InputReader {
-
- /**
- * Reads up to {@code readLength} bytes of data and stores them into {@code buffer},
- * starting at index {@code offset}.
- *
- * <p>This method blocks until at least one byte is read, the end of input is detected, or
- * an exception is thrown. The read position advances to the first unread byte.
- *
- * @param buffer The buffer into which the read data should be stored.
- * @param offset The start offset into {@code buffer} at which data should be written.
- * @param readLength The maximum number of bytes to read.
- * @return The non-zero number of bytes read, or -1 if no data is available because the end
- * of the input has been reached.
- * @throws java.io.IOException If an error occurs reading from the source.
- */
- int read(@NonNull byte[] buffer, int offset, int readLength) throws IOException;
-
- /** Returns the current read position (byte offset) in the stream. */
- long getPosition();
-
- /** Returns the length of the input in bytes, or -1 if the length is unknown. */
- long getLength();
- }
-
- /** {@link InputReader} that allows setting the read position. */
- public interface SeekableInputReader extends InputReader {
-
- /**
- * Sets the read position at the given {@code position}.
- *
- * <p>{@link #advance} will immediately return after calling this method.
- *
- * @param position The position to seek to, in bytes.
- */
- void seekToPosition(long position);
- }
-
- /** Receives extracted media sample data and metadata from {@link MediaParser}. */
- public interface OutputConsumer {
-
- /**
- * Called when a {@link SeekMap} has been extracted from the stream.
- *
- * <p>This method is called at least once before any samples are {@link #onSampleCompleted
- * complete}. May be called multiple times after that in order to add {@link SeekPoint
- * SeekPoints}.
- *
- * @param seekMap The extracted {@link SeekMap}.
- */
- void onSeekMapFound(@NonNull SeekMap seekMap);
-
- /**
- * Called when the number of tracks is found.
- *
- * @param numberOfTracks The number of tracks in the stream.
- */
- void onTrackCountFound(int numberOfTracks);
-
- /**
- * Called when new {@link TrackData} is found in the stream.
- *
- * @param trackIndex The index of the track for which the {@link TrackData} was extracted.
- * @param trackData The extracted {@link TrackData}.
- */
- void onTrackDataFound(int trackIndex, @NonNull TrackData trackData);
-
- /**
- * Called when sample data is found in the stream.
- *
- * <p>If the invocation of this method returns before the entire {@code inputReader} {@link
- * InputReader#getLength() length} is consumed, the method will be called again for the
- * implementer to read the remaining data. Implementers should surface any thrown {@link
- * IOException} caused by reading from {@code input}.
- *
- * @param trackIndex The index of the track to which the sample data corresponds.
- * @param inputReader The {@link InputReader} from which to read the data.
- * @throws IOException If an exception occurs while reading from {@code inputReader}.
- */
- void onSampleDataFound(int trackIndex, @NonNull InputReader inputReader) throws IOException;
-
- /**
- * Called once all the data of a sample has been passed to {@link #onSampleDataFound}.
- *
- * <p>Includes sample metadata, like presentation timestamp and flags.
- *
- * @param trackIndex The index of the track to which the sample corresponds.
- * @param timeMicros The media timestamp associated with the sample, in microseconds.
- * @param flags Flags associated with the sample. See the {@code SAMPLE_FLAG_*} constants.
- * @param size The size of the sample data, in bytes.
- * @param offset The number of bytes that have been consumed by {@code
- * onSampleDataFound(int, MediaParser.InputReader)} for the specified track, since the
- * last byte belonging to the sample whose metadata is being passed.
- * @param cryptoInfo Encryption data required to decrypt the sample. May be null for
- * unencrypted samples. Implementors should treat any output {@link CryptoInfo}
- * instances as immutable. MediaParser will not modify any output {@code cryptoInfos}
- * and implementors should not modify them either.
- */
- void onSampleCompleted(
- int trackIndex,
- long timeMicros,
- @SampleFlags int flags,
- int size,
- int offset,
- @Nullable CryptoInfo cryptoInfo);
- }
-
- /**
- * Thrown if all parser implementations provided to {@link #create} failed to sniff the input
- * content.
- */
- public static final class UnrecognizedInputFormatException extends IOException {
-
- /**
- * Creates a new instance which signals that the parsers with the given names failed to
- * parse the input.
- */
- @NonNull
- @CheckResult
- private static UnrecognizedInputFormatException createForExtractors(
- @NonNull String... extractorNames) {
- StringBuilder builder = new StringBuilder();
- builder.append("None of the available parsers ( ");
- builder.append(extractorNames[0]);
- for (int i = 1; i < extractorNames.length; i++) {
- builder.append(", ");
- builder.append(extractorNames[i]);
- }
- builder.append(") could read the stream.");
- return new UnrecognizedInputFormatException(builder.toString());
- }
-
- private UnrecognizedInputFormatException(String extractorNames) {
- super(extractorNames);
- }
- }
-
- /** Thrown when an error occurs while parsing a media stream. */
- public static final class ParsingException extends IOException {
-
- private ParsingException(ParserException cause) {
- super(cause);
- }
- }
-
- // Sample flags.
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(
- flag = true,
- value = {
- SAMPLE_FLAG_KEY_FRAME,
- SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA,
- SAMPLE_FLAG_LAST_SAMPLE,
- SAMPLE_FLAG_ENCRYPTED,
- SAMPLE_FLAG_DECODE_ONLY
- })
- public @interface SampleFlags {}
- /** Indicates that the sample holds a synchronization sample. */
- public static final int SAMPLE_FLAG_KEY_FRAME = MediaCodec.BUFFER_FLAG_KEY_FRAME;
- /**
- * Indicates that the sample has supplemental data.
- *
- * <p>Samples will not have this flag set unless the {@code
- * "android.media.mediaparser.includeSupplementalData"} parameter is set to {@code true} via
- * {@link #setParameter}.
- *
- * <p>Samples with supplemental data have the following sample data format:
- *
- * <ul>
- * <li>If the {@code "android.media.mediaparser.inBandCryptoInfo"} parameter is set, all
- * encryption information.
- * <li>(4 bytes) {@code sample_data_size}: The size of the actual sample data, not including
- * supplemental data or encryption information.
- * <li>({@code sample_data_size} bytes): The media sample data.
- * <li>(remaining bytes) The supplemental data.
- * </ul>
- */
- public static final int SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA = 1 << 28;
- /** Indicates that the sample is known to contain the last media sample of the stream. */
- public static final int SAMPLE_FLAG_LAST_SAMPLE = 1 << 29;
- /** Indicates that the sample is (at least partially) encrypted. */
- public static final int SAMPLE_FLAG_ENCRYPTED = 1 << 30;
- /** Indicates that the sample should be decoded but not rendered. */
- public static final int SAMPLE_FLAG_DECODE_ONLY = 1 << 31;
-
- // Parser implementation names.
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @StringDef(
- prefix = {"PARSER_NAME_"},
- value = {
- PARSER_NAME_UNKNOWN,
- PARSER_NAME_MATROSKA,
- PARSER_NAME_FMP4,
- PARSER_NAME_MP4,
- PARSER_NAME_MP3,
- PARSER_NAME_ADTS,
- PARSER_NAME_AC3,
- PARSER_NAME_TS,
- PARSER_NAME_FLV,
- PARSER_NAME_OGG,
- PARSER_NAME_PS,
- PARSER_NAME_WAV,
- PARSER_NAME_AMR,
- PARSER_NAME_AC4,
- PARSER_NAME_FLAC
- })
- public @interface ParserName {}
-
- /** Parser name returned by {@link #getParserName()} when no parser has been selected yet. */
- public static final String PARSER_NAME_UNKNOWN = "android.media.mediaparser.UNKNOWN";
- /**
- * Parser for the Matroska container format, as defined in the <a
- * href="https://matroska.org/technical/specs/">spec</a>.
- */
- public static final String PARSER_NAME_MATROSKA = "android.media.mediaparser.MatroskaParser";
- /**
- * Parser for fragmented files using the MP4 container format, as defined in ISO/IEC 14496-12.
- */
- public static final String PARSER_NAME_FMP4 = "android.media.mediaparser.FragmentedMp4Parser";
- /**
- * Parser for non-fragmented files using the MP4 container format, as defined in ISO/IEC
- * 14496-12.
- */
- public static final String PARSER_NAME_MP4 = "android.media.mediaparser.Mp4Parser";
- /** Parser for the MP3 container format, as defined in ISO/IEC 11172-3. */
- public static final String PARSER_NAME_MP3 = "android.media.mediaparser.Mp3Parser";
- /** Parser for the ADTS container format, as defined in ISO/IEC 13818-7. */
- public static final String PARSER_NAME_ADTS = "android.media.mediaparser.AdtsParser";
- /**
- * Parser for the AC-3 container format, as defined in Digital Audio Compression Standard
- * (AC-3).
- */
- public static final String PARSER_NAME_AC3 = "android.media.mediaparser.Ac3Parser";
- /** Parser for the TS container format, as defined in ISO/IEC 13818-1. */
- public static final String PARSER_NAME_TS = "android.media.mediaparser.TsParser";
- /**
- * Parser for the FLV container format, as defined in Adobe Flash Video File Format
- * Specification.
- */
- public static final String PARSER_NAME_FLV = "android.media.mediaparser.FlvParser";
- /** Parser for the OGG container format, as defined in RFC 3533. */
- public static final String PARSER_NAME_OGG = "android.media.mediaparser.OggParser";
- /** Parser for the PS container format, as defined in ISO/IEC 11172-1. */
- public static final String PARSER_NAME_PS = "android.media.mediaparser.PsParser";
- /**
- * Parser for the WAV container format, as defined in Multimedia Programming Interface and Data
- * Specifications.
- */
- public static final String PARSER_NAME_WAV = "android.media.mediaparser.WavParser";
- /** Parser for the AMR container format, as defined in RFC 4867. */
- public static final String PARSER_NAME_AMR = "android.media.mediaparser.AmrParser";
- /**
- * Parser for the AC-4 container format, as defined by Dolby AC-4: Audio delivery for
- * Next-Generation Entertainment Services.
- */
- public static final String PARSER_NAME_AC4 = "android.media.mediaparser.Ac4Parser";
- /**
- * Parser for the FLAC container format, as defined in the <a
- * href="https://xiph.org/flac/">spec</a>.
- */
- public static final String PARSER_NAME_FLAC = "android.media.mediaparser.FlacParser";
-
- // MediaParser parameters.
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @StringDef(
- prefix = {"PARAMETER_"},
- value = {
- PARAMETER_ADTS_ENABLE_CBR_SEEKING,
- PARAMETER_AMR_ENABLE_CBR_SEEKING,
- PARAMETER_FLAC_DISABLE_ID3,
- PARAMETER_MP4_IGNORE_EDIT_LISTS,
- PARAMETER_MP4_IGNORE_TFDT_BOX,
- PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES,
- PARAMETER_MATROSKA_DISABLE_CUES_SEEKING,
- PARAMETER_MP3_DISABLE_ID3,
- PARAMETER_MP3_ENABLE_CBR_SEEKING,
- PARAMETER_MP3_ENABLE_INDEX_SEEKING,
- PARAMETER_TS_MODE,
- PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES,
- PARAMETER_TS_IGNORE_AAC_STREAM,
- PARAMETER_TS_IGNORE_AVC_STREAM,
- PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM,
- PARAMETER_TS_DETECT_ACCESS_UNITS,
- PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS,
- PARAMETER_IN_BAND_CRYPTO_INFO,
- PARAMETER_INCLUDE_SUPPLEMENTAL_DATA
- })
- public @interface ParameterName {}
-
- /**
- * Sets whether constant bitrate seeking should be enabled for ADTS parsing. {@code boolean}
- * expected. Default value is {@code false}.
- */
- public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING =
- "android.media.mediaparser.adts.enableCbrSeeking";
- /**
- * Sets whether constant bitrate seeking should be enabled for AMR. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING =
- "android.media.mediaparser.amr.enableCbrSeeking";
- /**
- * Sets whether the ID3 track should be disabled for FLAC. {@code boolean} expected. Default
- * value is {@code false}.
- */
- public static final String PARAMETER_FLAC_DISABLE_ID3 =
- "android.media.mediaparser.flac.disableId3";
- /**
- * Sets whether MP4 parsing should ignore edit lists. {@code boolean} expected. Default value is
- * {@code false}.
- */
- public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS =
- "android.media.mediaparser.mp4.ignoreEditLists";
- /**
- * Sets whether MP4 parsing should ignore the tfdt box. {@code boolean} expected. Default value
- * is {@code false}.
- */
- public static final String PARAMETER_MP4_IGNORE_TFDT_BOX =
- "android.media.mediaparser.mp4.ignoreTfdtBox";
- /**
- * Sets whether MP4 parsing should treat all video frames as key frames. {@code boolean}
- * expected. Default value is {@code false}.
- */
- public static final String PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES =
- "android.media.mediaparser.mp4.treatVideoFramesAsKeyframes";
- /**
- * Sets whether Matroska parsing should avoid seeking to the cues element. {@code boolean}
- * expected. Default value is {@code false}.
- *
- * <p>If this flag is enabled and the cues element occurs after the first cluster, then the
- * media is treated as unseekable.
- */
- public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING =
- "android.media.mediaparser.matroska.disableCuesSeeking";
- /**
- * Sets whether the ID3 track should be disabled for MP3. {@code boolean} expected. Default
- * value is {@code false}.
- */
- public static final String PARAMETER_MP3_DISABLE_ID3 =
- "android.media.mediaparser.mp3.disableId3";
- /**
- * Sets whether constant bitrate seeking should be enabled for MP3. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING =
- "android.media.mediaparser.mp3.enableCbrSeeking";
- /**
- * Sets whether MP3 parsing should generate a time-to-byte mapping. {@code boolean} expected.
- * Default value is {@code false}.
- *
- * <p>Enabling this flag may require to scan a significant portion of the file to compute a seek
- * point. Therefore, it should only be used if:
- *
- * <ul>
- * <li>the file is small, or
- * <li>the bitrate is variable (or the type of bitrate is unknown) and the seeking metadata
- * provided in the file is not precise enough (or is not present).
- * </ul>
- */
- public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING =
- "android.media.mediaparser.mp3.enableIndexSeeking";
- /**
- * Sets the operation mode for TS parsing. {@code String} expected. Valid values are {@code
- * "single_pmt"}, {@code "multi_pmt"}, and {@code "hls"}. Default value is {@code "single_pmt"}.
- *
- * <p>The operation modes alter the way TS behaves so that it can handle certain kinds of
- * commonly-occurring malformed media.
- *
- * <ul>
- * <li>{@code "single_pmt"}: Only the first found PMT is parsed. Others are ignored, even if
- * more PMTs are declared in the PAT.
- * <li>{@code "multi_pmt"}: Behave as described in ISO/IEC 13818-1.
- * <li>{@code "hls"}: Enable {@code "single_pmt"} mode, and ignore continuity counters.
- * </ul>
- */
- public static final String PARAMETER_TS_MODE = "android.media.mediaparser.ts.mode";
- /**
- * Sets whether TS should treat samples consisting of non-IDR I slices as synchronization
- * samples (key-frames). {@code boolean} expected. Default value is {@code false}.
- */
- public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES =
- "android.media.mediaparser.ts.allowNonIdrAvcKeyframes";
- /**
- * Sets whether TS parsing should ignore AAC elementary streams. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_TS_IGNORE_AAC_STREAM =
- "android.media.mediaparser.ts.ignoreAacStream";
- /**
- * Sets whether TS parsing should ignore AVC elementary streams. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_TS_IGNORE_AVC_STREAM =
- "android.media.mediaparser.ts.ignoreAvcStream";
- /**
- * Sets whether TS parsing should ignore splice information streams. {@code boolean} expected.
- * Default value is {@code false}.
- */
- public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM =
- "android.media.mediaparser.ts.ignoreSpliceInfoStream";
- /**
- * Sets whether TS parsing should split AVC stream into access units based on slice headers.
- * {@code boolean} expected. Default value is {@code false}.
- *
- * <p>This flag should be left disabled if the stream contains access units delimiters in order
- * to avoid unnecessary computational costs.
- */
- public static final String PARAMETER_TS_DETECT_ACCESS_UNITS =
- "android.media.mediaparser.ts.ignoreDetectAccessUnits";
- /**
- * Sets whether TS parsing should handle HDMV DTS audio streams. {@code boolean} expected.
- * Default value is {@code false}.
- *
- * <p>Enabling this flag will disable the detection of SCTE subtitles.
- */
- public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS =
- "android.media.mediaparser.ts.enableHdmvDtsAudioStreams";
- /**
- * Sets whether encryption data should be sent in-band with the sample data, as per {@link
- * OutputConsumer#onSampleDataFound}. {@code boolean} expected. Default value is {@code false}.
- *
- * <p>If this parameter is set, encrypted samples' data will be prefixed with the encryption
- * information bytes. The format for in-band encryption information is:
- *
- * <ul>
- * <li>(1 byte) {@code encryption_signal_byte}: Most significant bit signals whether the
- * encryption data contains subsample encryption data. The remaining bits contain {@code
- * initialization_vector_size}.
- * <li>({@code initialization_vector_size} bytes) Initialization vector.
- * <li>If subsample encryption data is present, as per {@code encryption_signal_byte}, the
- * encryption data also contains:
- * <ul>
- * <li>(2 bytes) {@code subsample_encryption_data_length}.
- * <li>({@code subsample_encryption_data_length * 6} bytes) Subsample encryption data
- * (repeated {@code subsample_encryption_data_length} times):
- * <ul>
- * <li>(2 bytes) Size of a clear section in sample.
- * <li>(4 bytes) Size of an encryption section in sample.
- * </ul>
- * </ul>
- * </ul>
- *
- * @hide
- */
- public static final String PARAMETER_IN_BAND_CRYPTO_INFO =
- "android.media.mediaparser.inBandCryptoInfo";
- /**
- * Sets whether supplemental data should be included as part of the sample data. {@code boolean}
- * expected. Default value is {@code false}. See {@link #SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA} for
- * information about the sample data format.
- *
- * @hide
- */
- public static final String PARAMETER_INCLUDE_SUPPLEMENTAL_DATA =
- "android.media.mediaparser.includeSupplementalData";
- /**
- * Sets whether sample timestamps may start from non-zero offsets. {@code boolean} expected.
- * Default value is {@code false}.
- *
- * <p>When set to true, sample timestamps will not be offset to start from zero, and the media
- * provided timestamps will be used instead. For example, transport stream sample timestamps
- * will not be converted to a zero-based timebase.
- *
- * @hide
- */
- public static final String PARAMETER_IGNORE_TIMESTAMP_OFFSET =
- "android.media.mediaparser.ignoreTimestampOffset";
- /**
- * Sets whether each track type should be eagerly exposed. {@code boolean} expected. Default
- * value is {@code false}.
- *
- * <p>When set to true, each track type will be eagerly exposed through a call to {@link
- * OutputConsumer#onTrackDataFound} containing a single-value {@link MediaFormat}. The key for
- * the track type is {@code "track-type-string"}, and the possible values are {@code "video"},
- * {@code "audio"}, {@code "text"}, {@code "metadata"}, and {@code "unknown"}.
- *
- * @hide
- */
- public static final String PARAMETER_EAGERLY_EXPOSE_TRACKTYPE =
- "android.media.mediaparser.eagerlyExposeTrackType";
- /**
- * Sets whether a dummy {@link SeekMap} should be exposed before starting extraction. {@code
- * boolean} expected. Default value is {@code false}.
- *
- * <p>For each {@link SeekMap#getSeekPoints} call, the dummy {@link SeekMap} returns a single
- * {@link SeekPoint} whose {@link SeekPoint#timeMicros} matches the requested timestamp, and
- * whose {@link SeekPoint#position} is 0.
- *
- * @hide
- */
- public static final String PARAMETER_EXPOSE_DUMMY_SEEKMAP =
- "android.media.mediaparser.exposeDummySeekMap";
-
- /**
- * Sets whether chunk indices available in the extracted media should be exposed as {@link
- * MediaFormat MediaFormats}. {@code boolean} expected. Default value is {@link false}.
- *
- * <p>When set to true, any information about media segmentation will be exposed as a {@link
- * MediaFormat} (with track index 0) containing four {@link ByteBuffer} elements under the
- * following keys:
- *
- * <ul>
- * <li>"chunk-index-int-sizes": Contains {@code ints} representing the sizes in bytes of each
- * of the media segments.
- * <li>"chunk-index-long-offsets": Contains {@code longs} representing the byte offsets of
- * each segment in the stream.
- * <li>"chunk-index-long-us-durations": Contains {@code longs} representing the media duration
- * of each segment, in microseconds.
- * <li>"chunk-index-long-us-times": Contains {@code longs} representing the start time of each
- * segment, in microseconds.
- * </ul>
- *
- * @hide
- */
- public static final String PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT =
- "android.media.mediaParser.exposeChunkIndexAsMediaFormat";
- /**
- * Sets a list of closed-caption {@link MediaFormat MediaFormats} that should be exposed as part
- * of the extracted media. {@code List<MediaFormat>} expected. Default value is an empty list.
- *
- * <p>Expected keys in the {@link MediaFormat} are:
- *
- * <ul>
- * <p>{@link MediaFormat#KEY_MIME}: Determine the type of captions (for example,
- * application/cea-608). Mandatory.
- * <p>{@link MediaFormat#KEY_CAPTION_SERVICE_NUMBER}: Determine the channel on which the
- * captions are transmitted. Optional.
- * </ul>
- *
- * @hide
- */
- public static final String PARAMETER_EXPOSE_CAPTION_FORMATS =
- "android.media.mediaParser.exposeCaptionFormats";
- /**
- * Sets whether the value associated with {@link #PARAMETER_EXPOSE_CAPTION_FORMATS} should
- * override any in-band caption service declarations. {@code boolean} expected. Default value is
- * {@link false}.
- *
- * <p>When {@code false}, any present in-band caption services information will override the
- * values associated with {@link #PARAMETER_EXPOSE_CAPTION_FORMATS}.
- *
- * @hide
- */
- public static final String PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS =
- "android.media.mediaParser.overrideInBandCaptionDeclarations";
- /**
- * Sets whether a track for EMSG events should be exposed in case of parsing a container that
- * supports them. {@code boolean} expected. Default value is {@link false}.
- *
- * @hide
- */
- public static final String PARAMETER_EXPOSE_EMSG_TRACK =
- "android.media.mediaParser.exposeEmsgTrack";
-
- // Private constants.
-
- private static final String TAG = "MediaParser";
- private static final String JNI_LIBRARY_NAME = "mediaparser-jni";
- private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
- private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
- private static final String TS_MODE_SINGLE_PMT = "single_pmt";
- private static final String TS_MODE_MULTI_PMT = "multi_pmt";
- private static final String TS_MODE_HLS = "hls";
- private static final int BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY = 6;
- private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
- private static final String MEDIAMETRICS_ELEMENT_SEPARATOR = "|";
- private static final int MEDIAMETRICS_MAX_STRING_SIZE = 200;
- private static final int MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH;
- /**
- * Intentional error introduced to reported metrics to prevent identification of the parsed
- * media. Note: Increasing this value may cause older hostside CTS tests to fail.
- */
- private static final float MEDIAMETRICS_DITHER = .02f;
-
- @IntDef(
- value = {
- STATE_READING_SIGNAL_BYTE,
- STATE_READING_INIT_VECTOR,
- STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE,
- STATE_READING_SUBSAMPLE_ENCRYPTION_DATA
- })
- private @interface EncryptionDataReadState {}
-
- private static final int STATE_READING_SIGNAL_BYTE = 0;
- private static final int STATE_READING_INIT_VECTOR = 1;
- private static final int STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE = 2;
- private static final int STATE_READING_SUBSAMPLE_ENCRYPTION_DATA = 3;
-
- // Instance creation methods.
-
- /**
- * Creates an instance backed by the parser with the given {@code name}. The returned instance
- * will attempt parsing without sniffing the content.
- *
- * @param name The name of the parser that will be associated with the created instance.
- * @param outputConsumer The {@link OutputConsumer} to which track data and samples are pushed.
- * @return A new instance.
- * @throws IllegalArgumentException If an invalid name is provided.
- */
- @NonNull
- public static MediaParser createByName(
- @NonNull @ParserName String name, @NonNull OutputConsumer outputConsumer) {
- String[] nameAsArray = new String[] {name};
- assertValidNames(nameAsArray);
- return new MediaParser(outputConsumer, /* createdByName= */ true, name);
- }
-
- /**
- * Creates an instance whose backing parser will be selected by sniffing the content during the
- * first {@link #advance} call. Parser implementations will sniff the content in order of
- * appearance in {@code parserNames}.
- *
- * @param outputConsumer The {@link OutputConsumer} to which extracted data is output.
- * @param parserNames The names of the parsers to sniff the content with. If empty, a default
- * array of names is used.
- * @return A new instance.
- */
- @NonNull
- public static MediaParser create(
- @NonNull OutputConsumer outputConsumer, @NonNull @ParserName String... parserNames) {
- assertValidNames(parserNames);
- if (parserNames.length == 0) {
- parserNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
- }
- return new MediaParser(outputConsumer, /* createdByName= */ false, parserNames);
- }
-
- // Misc static methods.
-
- /**
- * Returns an immutable list with the names of the parsers that are suitable for container
- * formats with the given {@link MediaFormat}.
- *
- * <p>A parser supports a {@link MediaFormat} if the mime type associated with {@link
- * MediaFormat#KEY_MIME} corresponds to the supported container format.
- *
- * @param mediaFormat The {@link MediaFormat} to check support for.
- * @return The parser names that support the given {@code mediaFormat}, or the list of all
- * parsers available if no container specific format information is provided.
- */
- @NonNull
- @ParserName
- public static List<String> getParserNames(@NonNull MediaFormat mediaFormat) {
- String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
- mimeType = mimeType == null ? null : Util.toLowerInvariant(mimeType.trim());
- if (TextUtils.isEmpty(mimeType)) {
- // No MIME type provided. Return all.
- return Collections.unmodifiableList(
- new ArrayList<>(EXTRACTOR_FACTORIES_BY_NAME.keySet()));
- }
- ArrayList<String> result = new ArrayList<>();
- switch (mimeType) {
- case "video/x-matroska":
- case "audio/x-matroska":
- case "video/x-webm":
- case "audio/x-webm":
- result.add(PARSER_NAME_MATROSKA);
- break;
- case "video/mp4":
- case "audio/mp4":
- case "application/mp4":
- result.add(PARSER_NAME_MP4);
- result.add(PARSER_NAME_FMP4);
- break;
- case "audio/mpeg":
- result.add(PARSER_NAME_MP3);
- break;
- case "audio/aac":
- result.add(PARSER_NAME_ADTS);
- break;
- case "audio/ac3":
- result.add(PARSER_NAME_AC3);
- break;
- case "video/mp2t":
- case "audio/mp2t":
- result.add(PARSER_NAME_TS);
- break;
- case "video/x-flv":
- result.add(PARSER_NAME_FLV);
- break;
- case "video/ogg":
- case "audio/ogg":
- case "application/ogg":
- result.add(PARSER_NAME_OGG);
- break;
- case "video/mp2p":
- case "video/mp1s":
- result.add(PARSER_NAME_PS);
- break;
- case "audio/vnd.wave":
- case "audio/wav":
- case "audio/wave":
- case "audio/x-wav":
- result.add(PARSER_NAME_WAV);
- break;
- case "audio/amr":
- result.add(PARSER_NAME_AMR);
- break;
- case "audio/ac4":
- result.add(PARSER_NAME_AC4);
- break;
- case "audio/flac":
- case "audio/x-flac":
- result.add(PARSER_NAME_FLAC);
- break;
- default:
- // No parsers support the given mime type. Do nothing.
- break;
- }
- return Collections.unmodifiableList(result);
- }
-
- // Private fields.
-
- private final Map<String, Object> mParserParameters;
- private final OutputConsumer mOutputConsumer;
- private final String[] mParserNamesPool;
- private final PositionHolder mPositionHolder;
- private final InputReadingDataReader mExoDataReader;
- private final DataReaderAdapter mScratchDataReaderAdapter;
- private final ParsableByteArrayAdapter mScratchParsableByteArrayAdapter;
- @Nullable private final Constructor<DrmInitData.SchemeInitData> mSchemeInitDataConstructor;
- private final ArrayList<Format> mMuxedCaptionFormats;
- private boolean mInBandCryptoInfo;
- private boolean mIncludeSupplementalData;
- private boolean mIgnoreTimestampOffset;
- private boolean mEagerlyExposeTrackType;
- private boolean mExposeDummySeekMap;
- private boolean mExposeChunkIndexAsMediaFormat;
- private String mParserName;
- private Extractor mExtractor;
- private ExtractorInput mExtractorInput;
- private boolean mPendingExtractorInit;
- private long mPendingSeekPosition;
- private long mPendingSeekTimeMicros;
- private boolean mLoggedSchemeInitDataCreationException;
- private boolean mReleased;
-
- // MediaMetrics fields.
- @Nullable private LogSessionId mLogSessionId;
- private final boolean mCreatedByName;
- private final SparseArray<Format> mTrackFormats;
- private String mLastObservedExceptionName;
- private long mDurationMillis;
- private long mResourceByteCount;
-
- // Public methods.
-
- /**
- * Sets parser-specific parameters which allow customizing behavior.
- *
- * <p>Must be called before the first call to {@link #advance}.
- *
- * @param parameterName The name of the parameter to set. See {@code PARAMETER_*} constants for
- * documentation on possible values.
- * @param value The value to set for the given {@code parameterName}. See {@code PARAMETER_*}
- * constants for documentation on the expected types.
- * @return This instance, for convenience.
- * @throws IllegalStateException If called after calling {@link #advance} on the same instance.
- */
- @NonNull
- public MediaParser setParameter(
- @NonNull @ParameterName String parameterName, @NonNull Object value) {
- if (mExtractor != null) {
- throw new IllegalStateException(
- "setParameters() must be called before the first advance() call.");
- }
- Class expectedType = EXPECTED_TYPE_BY_PARAMETER_NAME.get(parameterName);
- // Ignore parameter names that are not contained in the map, in case the client is passing
- // a parameter that is being added in a future version of this library.
- if (expectedType != null && !expectedType.isInstance(value)) {
- throw new IllegalArgumentException(
- parameterName
- + " expects a "
- + expectedType.getSimpleName()
- + " but a "
- + value.getClass().getSimpleName()
- + " was passed.");
- }
- if (PARAMETER_TS_MODE.equals(parameterName)
- && !TS_MODE_SINGLE_PMT.equals(value)
- && !TS_MODE_HLS.equals(value)
- && !TS_MODE_MULTI_PMT.equals(value)) {
- throw new IllegalArgumentException(PARAMETER_TS_MODE + " does not accept: " + value);
- }
- if (PARAMETER_IN_BAND_CRYPTO_INFO.equals(parameterName)) {
- mInBandCryptoInfo = (boolean) value;
- }
- if (PARAMETER_INCLUDE_SUPPLEMENTAL_DATA.equals(parameterName)) {
- mIncludeSupplementalData = (boolean) value;
- }
- if (PARAMETER_IGNORE_TIMESTAMP_OFFSET.equals(parameterName)) {
- mIgnoreTimestampOffset = (boolean) value;
- }
- if (PARAMETER_EAGERLY_EXPOSE_TRACKTYPE.equals(parameterName)) {
- mEagerlyExposeTrackType = (boolean) value;
- }
- if (PARAMETER_EXPOSE_DUMMY_SEEKMAP.equals(parameterName)) {
- mExposeDummySeekMap = (boolean) value;
- }
- if (PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT.equals(parameterName)) {
- mExposeChunkIndexAsMediaFormat = (boolean) value;
- }
- if (PARAMETER_EXPOSE_CAPTION_FORMATS.equals(parameterName)) {
- setMuxedCaptionFormats((List<MediaFormat>) value);
- }
- mParserParameters.put(parameterName, value);
- return this;
- }
-
- /**
- * Returns whether the given {@code parameterName} is supported by this parser.
- *
- * @param parameterName The parameter name to check support for. One of the {@code PARAMETER_*}
- * constants.
- * @return Whether the given {@code parameterName} is supported.
- */
- public boolean supportsParameter(@NonNull @ParameterName String parameterName) {
- return EXPECTED_TYPE_BY_PARAMETER_NAME.containsKey(parameterName);
- }
-
- /**
- * Returns the name of the backing parser implementation.
- *
- * <p>If this instance was creating using {@link #createByName}, the provided name is returned.
- * If this instance was created using {@link #create}, this method will return {@link
- * #PARSER_NAME_UNKNOWN} until the first call to {@link #advance}, after which the name of the
- * backing parser implementation is returned.
- *
- * @return The name of the backing parser implementation, or null if the backing parser
- * implementation has not yet been selected.
- */
- @NonNull
- @ParserName
- public String getParserName() {
- return mParserName;
- }
-
- /**
- * Makes progress in the extraction of the input media stream, unless the end of the input has
- * been reached.
- *
- * <p>This method will block until some progress has been made.
- *
- * <p>If this instance was created using {@link #create}, the first call to this method will
- * sniff the content using the selected parser implementations.
- *
- * @param seekableInputReader The {@link SeekableInputReader} from which to obtain the media
- * container data.
- * @return Whether there is any data left to extract. Returns false if the end of input has been
- * reached.
- * @throws IOException If an error occurs while reading from the {@link SeekableInputReader}.
- * @throws UnrecognizedInputFormatException If the format cannot be recognized by any of the
- * underlying parser implementations.
- */
- public boolean advance(@NonNull SeekableInputReader seekableInputReader) throws IOException {
- if (mExtractorInput == null) {
- // TODO: For efficiency, the same implementation should be used, by providing a
- // clearBuffers() method, or similar.
- long resourceLength = seekableInputReader.getLength();
- if (mResourceByteCount == 0) {
- // For resource byte count metric collection, we only take into account the length
- // of the first provided input reader.
- mResourceByteCount = resourceLength;
- }
- mExtractorInput =
- new DefaultExtractorInput(
- mExoDataReader, seekableInputReader.getPosition(), resourceLength);
- }
- mExoDataReader.mInputReader = seekableInputReader;
-
- if (mExtractor == null) {
- mPendingExtractorInit = true;
- if (!mParserName.equals(PARSER_NAME_UNKNOWN)) {
- mExtractor = createExtractor(mParserName);
- } else {
- for (String parserName : mParserNamesPool) {
- Extractor extractor = createExtractor(parserName);
- try {
- if (extractor.sniff(mExtractorInput)) {
- mParserName = parserName;
- mExtractor = extractor;
- mPendingExtractorInit = true;
- break;
- }
- } catch (EOFException e) {
- // Do nothing.
- } finally {
- mExtractorInput.resetPeekPosition();
- }
- }
- if (mExtractor == null) {
- UnrecognizedInputFormatException exception =
- UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
- mLastObservedExceptionName = exception.getClass().getName();
- throw exception;
- }
- return true;
- }
- }
-
- if (mPendingExtractorInit) {
- if (mExposeDummySeekMap) {
- // We propagate the dummy seek map before initializing the extractor, in case the
- // extractor initialization outputs a seek map.
- mOutputConsumer.onSeekMapFound(SeekMap.DUMMY);
- }
- mExtractor.init(new ExtractorOutputAdapter());
- mPendingExtractorInit = false;
- // We return after initialization to allow clients use any output information before
- // starting actual extraction.
- return true;
- }
-
- if (isPendingSeek()) {
- mExtractor.seek(mPendingSeekPosition, mPendingSeekTimeMicros);
- removePendingSeek();
- }
-
- mPositionHolder.position = seekableInputReader.getPosition();
- int result;
- try {
- result = mExtractor.read(mExtractorInput, mPositionHolder);
- } catch (Exception e) {
- mLastObservedExceptionName = e.getClass().getName();
- if (e instanceof ParserException) {
- throw new ParsingException((ParserException) e);
- } else {
- throw e;
- }
- }
- if (result == Extractor.RESULT_END_OF_INPUT) {
- mExtractorInput = null;
- return false;
- }
- if (result == Extractor.RESULT_SEEK) {
- mExtractorInput = null;
- seekableInputReader.seekToPosition(mPositionHolder.position);
- }
- return true;
- }
-
- /**
- * Seeks within the media container being extracted.
- *
- * <p>{@link SeekPoint SeekPoints} can be obtained from the {@link SeekMap} passed to {@link
- * OutputConsumer#onSeekMapFound(SeekMap)}.
- *
- * <p>Following a call to this method, the {@link InputReader} passed to the next invocation of
- * {@link #advance} must provide data starting from {@link SeekPoint#position} in the stream.
- *
- * @param seekPoint The {@link SeekPoint} to seek to.
- */
- public void seek(@NonNull SeekPoint seekPoint) {
- if (mExtractor == null) {
- mPendingSeekPosition = seekPoint.position;
- mPendingSeekTimeMicros = seekPoint.timeMicros;
- } else {
- mExtractor.seek(seekPoint.position, seekPoint.timeMicros);
- }
- }
-
- /**
- * Releases any acquired resources.
- *
- * <p>After calling this method, this instance becomes unusable and no other methods should be
- * invoked.
- */
- public void release() {
- mExtractorInput = null;
- mExtractor = null;
- if (mReleased) {
- // Nothing to do.
- return;
- }
- mReleased = true;
-
- String trackMimeTypes = buildMediaMetricsString(format -> format.sampleMimeType);
- String trackCodecs = buildMediaMetricsString(format -> format.codecs);
- int videoWidth = -1;
- int videoHeight = -1;
- for (int i = 0; i < mTrackFormats.size(); i++) {
- Format format = mTrackFormats.valueAt(i);
- if (format.width != Format.NO_VALUE && format.height != Format.NO_VALUE) {
- videoWidth = format.width;
- videoHeight = format.height;
- break;
- }
- }
-
- String alteredParameters =
- String.join(
- MEDIAMETRICS_ELEMENT_SEPARATOR,
- mParserParameters.keySet().toArray(new String[0]));
- alteredParameters =
- alteredParameters.substring(
- 0,
- Math.min(
- alteredParameters.length(),
- MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH));
-
- nativeSubmitMetrics(
- SdkLevel.isAtLeastS() ? getLogSessionIdStringV31() : "",
- mParserName,
- mCreatedByName,
- String.join(MEDIAMETRICS_ELEMENT_SEPARATOR, mParserNamesPool),
- mLastObservedExceptionName,
- addDither(mResourceByteCount),
- addDither(mDurationMillis),
- trackMimeTypes,
- trackCodecs,
- alteredParameters,
- videoWidth,
- videoHeight);
- }
-
- @RequiresApi(31)
- public void setLogSessionId(@NonNull LogSessionId logSessionId) {
- this.mLogSessionId = Objects.requireNonNull(logSessionId);
- }
-
- @RequiresApi(31)
- @NonNull
- public LogSessionId getLogSessionId() {
- return mLogSessionId != null ? mLogSessionId : LogSessionId.LOG_SESSION_ID_NONE;
- }
-
- // Private methods.
-
- private MediaParser(
- OutputConsumer outputConsumer, boolean createdByName, String... parserNamesPool) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
- throw new UnsupportedOperationException("Android version must be R or greater.");
- }
- mParserParameters = new HashMap<>();
- mOutputConsumer = outputConsumer;
- mParserNamesPool = parserNamesPool;
- mCreatedByName = createdByName;
- mParserName = createdByName ? parserNamesPool[0] : PARSER_NAME_UNKNOWN;
- mPositionHolder = new PositionHolder();
- mExoDataReader = new InputReadingDataReader();
- removePendingSeek();
- mScratchDataReaderAdapter = new DataReaderAdapter();
- mScratchParsableByteArrayAdapter = new ParsableByteArrayAdapter();
- mSchemeInitDataConstructor = getSchemeInitDataConstructor();
- mMuxedCaptionFormats = new ArrayList<>();
-
- // MediaMetrics.
- mTrackFormats = new SparseArray<>();
- mLastObservedExceptionName = "";
- mDurationMillis = -1;
- }
-
- private String buildMediaMetricsString(Function<Format, String> formatFieldGetter) {
- StringBuilder stringBuilder = new StringBuilder();
- for (int i = 0; i < mTrackFormats.size(); i++) {
- if (i > 0) {
- stringBuilder.append(MEDIAMETRICS_ELEMENT_SEPARATOR);
- }
- String fieldValue = formatFieldGetter.apply(mTrackFormats.valueAt(i));
- stringBuilder.append(fieldValue != null ? fieldValue : "");
- }
- return stringBuilder.substring(
- 0, Math.min(stringBuilder.length(), MEDIAMETRICS_MAX_STRING_SIZE));
- }
-
- private void setMuxedCaptionFormats(List<MediaFormat> mediaFormats) {
- mMuxedCaptionFormats.clear();
- for (MediaFormat mediaFormat : mediaFormats) {
- mMuxedCaptionFormats.add(toExoPlayerCaptionFormat(mediaFormat));
- }
- }
-
- private boolean isPendingSeek() {
- return mPendingSeekPosition >= 0;
- }
-
- private void removePendingSeek() {
- mPendingSeekPosition = -1;
- mPendingSeekTimeMicros = -1;
- }
-
- private Extractor createExtractor(String parserName) {
- int flags = 0;
- TimestampAdjuster timestampAdjuster = null;
- if (mIgnoreTimestampOffset) {
- timestampAdjuster = new TimestampAdjuster(TimestampAdjuster.DO_NOT_OFFSET);
- }
- switch (parserName) {
- case PARSER_NAME_MATROSKA:
- flags =
- getBooleanParameter(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING)
- ? MatroskaExtractor.FLAG_DISABLE_SEEK_FOR_CUES
- : 0;
- return new MatroskaExtractor(flags);
- case PARSER_NAME_FMP4:
- flags |=
- getBooleanParameter(PARAMETER_EXPOSE_EMSG_TRACK)
- ? FragmentedMp4Extractor.FLAG_ENABLE_EMSG_TRACK
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
- ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_MP4_IGNORE_TFDT_BOX)
- ? FragmentedMp4Extractor.FLAG_WORKAROUND_IGNORE_TFDT_BOX
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES)
- ? FragmentedMp4Extractor
- .FLAG_WORKAROUND_EVERY_VIDEO_FRAME_IS_SYNC_FRAME
- : 0;
- return new FragmentedMp4Extractor(
- flags,
- timestampAdjuster,
- /* sideloadedTrack= */ null,
- mMuxedCaptionFormats);
- case PARSER_NAME_MP4:
- flags |=
- getBooleanParameter(PARAMETER_MP4_IGNORE_EDIT_LISTS)
- ? Mp4Extractor.FLAG_WORKAROUND_IGNORE_EDIT_LISTS
- : 0;
- return new Mp4Extractor(flags);
- case PARSER_NAME_MP3:
- flags |=
- getBooleanParameter(PARAMETER_MP3_DISABLE_ID3)
- ? Mp3Extractor.FLAG_DISABLE_ID3_METADATA
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_MP3_ENABLE_CBR_SEEKING)
- ? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
- : 0;
- // TODO: Add index seeking once we update the ExoPlayer version.
- return new Mp3Extractor(flags);
- case PARSER_NAME_ADTS:
- flags |=
- getBooleanParameter(PARAMETER_ADTS_ENABLE_CBR_SEEKING)
- ? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
- : 0;
- return new AdtsExtractor(flags);
- case PARSER_NAME_AC3:
- return new Ac3Extractor();
- case PARSER_NAME_TS:
- flags |=
- getBooleanParameter(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES)
- ? DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_TS_DETECT_ACCESS_UNITS)
- ? DefaultTsPayloadReaderFactory.FLAG_DETECT_ACCESS_UNITS
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS)
- ? DefaultTsPayloadReaderFactory.FLAG_ENABLE_HDMV_DTS_AUDIO_STREAMS
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_TS_IGNORE_AAC_STREAM)
- ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_AAC_STREAM
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_TS_IGNORE_AVC_STREAM)
- ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_H264_STREAM
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM)
- ? DefaultTsPayloadReaderFactory.FLAG_IGNORE_SPLICE_INFO_STREAM
- : 0;
- flags |=
- getBooleanParameter(PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS)
- ? DefaultTsPayloadReaderFactory.FLAG_OVERRIDE_CAPTION_DESCRIPTORS
- : 0;
- String tsMode = getStringParameter(PARAMETER_TS_MODE, TS_MODE_SINGLE_PMT);
- int hlsMode =
- TS_MODE_SINGLE_PMT.equals(tsMode)
- ? TsExtractor.MODE_SINGLE_PMT
- : TS_MODE_HLS.equals(tsMode)
- ? TsExtractor.MODE_HLS
- : TsExtractor.MODE_MULTI_PMT;
- return new TsExtractor(
- hlsMode,
- timestampAdjuster != null
- ? timestampAdjuster
- : new TimestampAdjuster(/* firstSampleTimestampUs= */ 0),
- new DefaultTsPayloadReaderFactory(flags, mMuxedCaptionFormats));
- case PARSER_NAME_FLV:
- return new FlvExtractor();
- case PARSER_NAME_OGG:
- return new OggExtractor();
- case PARSER_NAME_PS:
- return new PsExtractor();
- case PARSER_NAME_WAV:
- return new WavExtractor();
- case PARSER_NAME_AMR:
- flags |=
- getBooleanParameter(PARAMETER_AMR_ENABLE_CBR_SEEKING)
- ? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING
- : 0;
- return new AmrExtractor(flags);
- case PARSER_NAME_AC4:
- return new Ac4Extractor();
- case PARSER_NAME_FLAC:
- flags |=
- getBooleanParameter(PARAMETER_FLAC_DISABLE_ID3)
- ? FlacExtractor.FLAG_DISABLE_ID3_METADATA
- : 0;
- return new FlacExtractor(flags);
- default:
- // Should never happen.
- throw new IllegalStateException("Unexpected attempt to create: " + parserName);
- }
- }
-
- private boolean getBooleanParameter(String name) {
- return (boolean) mParserParameters.getOrDefault(name, false);
- }
-
- private String getStringParameter(String name, String defaultValue) {
- return (String) mParserParameters.getOrDefault(name, defaultValue);
- }
-
- @RequiresApi(31)
- private String getLogSessionIdStringV31() {
- return mLogSessionId != null ? mLogSessionId.getStringId() : "";
- }
-
- // Private classes.
-
- private static final class InputReadingDataReader implements DataReader {
-
- public InputReader mInputReader;
-
- @Override
- public int read(byte[] buffer, int offset, int readLength) throws IOException {
- return mInputReader.read(buffer, offset, readLength);
- }
- }
-
- private final class MediaParserDrmInitData extends DrmInitData {
-
- private final SchemeInitData[] mSchemeDatas;
-
- private MediaParserDrmInitData(com.google.android.exoplayer2.drm.DrmInitData exoDrmInitData)
- throws IllegalAccessException, InstantiationException, InvocationTargetException {
- mSchemeDatas = new SchemeInitData[exoDrmInitData.schemeDataCount];
- for (int i = 0; i < mSchemeDatas.length; i++) {
- mSchemeDatas[i] = toFrameworkSchemeInitData(exoDrmInitData.get(i));
- }
- }
-
- @Override
- @Nullable
- public SchemeInitData get(UUID schemeUuid) {
- for (SchemeInitData schemeInitData : mSchemeDatas) {
- if (schemeInitData.uuid.equals(schemeUuid)) {
- return schemeInitData;
- }
- }
- return null;
- }
-
- @Override
- public SchemeInitData getSchemeInitDataAt(int index) {
- return mSchemeDatas[index];
- }
-
- @Override
- public int getSchemeInitDataCount() {
- return mSchemeDatas.length;
- }
-
- private DrmInitData.SchemeInitData toFrameworkSchemeInitData(SchemeData exoSchemeData)
- throws IllegalAccessException, InvocationTargetException, InstantiationException {
- return mSchemeInitDataConstructor.newInstance(
- exoSchemeData.uuid, exoSchemeData.mimeType, exoSchemeData.data);
- }
- }
-
- private final class ExtractorOutputAdapter implements ExtractorOutput {
-
- private final SparseArray<TrackOutput> mTrackOutputAdapters;
- private boolean mTracksEnded;
-
- private ExtractorOutputAdapter() {
- mTrackOutputAdapters = new SparseArray<>();
- }
-
- @Override
- public TrackOutput track(int id, int type) {
- TrackOutput trackOutput = mTrackOutputAdapters.get(id);
- if (trackOutput == null) {
- int trackIndex = mTrackOutputAdapters.size();
- trackOutput = new TrackOutputAdapter(trackIndex);
- mTrackOutputAdapters.put(id, trackOutput);
- if (mEagerlyExposeTrackType) {
- MediaFormat mediaFormat = new MediaFormat();
- mediaFormat.setString("track-type-string", toTypeString(type));
- mOutputConsumer.onTrackDataFound(
- trackIndex, new TrackData(mediaFormat, /* drmInitData= */ null));
- }
- }
- return trackOutput;
- }
-
- @Override
- public void endTracks() {
- mOutputConsumer.onTrackCountFound(mTrackOutputAdapters.size());
- }
-
- @Override
- public void seekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
- long durationUs = exoplayerSeekMap.getDurationUs();
- if (durationUs != C.TIME_UNSET) {
- mDurationMillis = C.usToMs(durationUs);
- }
- if (mExposeChunkIndexAsMediaFormat && exoplayerSeekMap instanceof ChunkIndex) {
- ChunkIndex chunkIndex = (ChunkIndex) exoplayerSeekMap;
- MediaFormat mediaFormat = new MediaFormat();
- mediaFormat.setByteBuffer("chunk-index-int-sizes", toByteBuffer(chunkIndex.sizes));
- mediaFormat.setByteBuffer(
- "chunk-index-long-offsets", toByteBuffer(chunkIndex.offsets));
- mediaFormat.setByteBuffer(
- "chunk-index-long-us-durations", toByteBuffer(chunkIndex.durationsUs));
- mediaFormat.setByteBuffer(
- "chunk-index-long-us-times", toByteBuffer(chunkIndex.timesUs));
- mOutputConsumer.onTrackDataFound(
- /* trackIndex= */ 0, new TrackData(mediaFormat, /* drmInitData= */ null));
- }
- mOutputConsumer.onSeekMapFound(new SeekMap(exoplayerSeekMap));
- }
- }
-
- private class TrackOutputAdapter implements TrackOutput {
-
- private final int mTrackIndex;
-
- private CryptoInfo mLastOutputCryptoInfo;
- private CryptoInfo.Pattern mLastOutputEncryptionPattern;
- private CryptoData mLastReceivedCryptoData;
-
- @EncryptionDataReadState private int mEncryptionDataReadState;
- private int mEncryptionDataSizeToSubtractFromSampleDataSize;
- private int mEncryptionVectorSize;
- private byte[] mScratchIvSpace;
- private int mSubsampleEncryptionDataSize;
- private int[] mScratchSubsampleEncryptedBytesCount;
- private int[] mScratchSubsampleClearBytesCount;
- private boolean mHasSubsampleEncryptionData;
- private int mSkippedSupplementalDataBytes;
-
- private TrackOutputAdapter(int trackIndex) {
- mTrackIndex = trackIndex;
- mScratchIvSpace = new byte[16]; // Size documented in CryptoInfo.
- mScratchSubsampleEncryptedBytesCount = new int[32];
- mScratchSubsampleClearBytesCount = new int[32];
- mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
- mLastOutputEncryptionPattern =
- new CryptoInfo.Pattern(/* blocksToEncrypt= */ 0, /* blocksToSkip= */ 0);
- }
-
- @Override
- public void format(Format format) {
- mTrackFormats.put(mTrackIndex, format);
- mOutputConsumer.onTrackDataFound(
- mTrackIndex,
- new TrackData(
- toMediaFormat(format), toFrameworkDrmInitData(format.drmInitData)));
- }
-
- @Override
- public int sampleData(
- DataReader input,
- int length,
- boolean allowEndOfInput,
- @SampleDataPart int sampleDataPart)
- throws IOException {
- mScratchDataReaderAdapter.setDataReader(input, length);
- long positionBeforeReading = mScratchDataReaderAdapter.getPosition();
- mOutputConsumer.onSampleDataFound(mTrackIndex, mScratchDataReaderAdapter);
- return (int) (mScratchDataReaderAdapter.getPosition() - positionBeforeReading);
- }
-
- @Override
- public void sampleData(
- ParsableByteArray data, int length, @SampleDataPart int sampleDataPart) {
- if (sampleDataPart == SAMPLE_DATA_PART_ENCRYPTION && !mInBandCryptoInfo) {
- while (length > 0) {
- switch (mEncryptionDataReadState) {
- case STATE_READING_SIGNAL_BYTE:
- int encryptionSignalByte = data.readUnsignedByte();
- length--;
- mHasSubsampleEncryptionData = ((encryptionSignalByte >> 7) & 1) != 0;
- mEncryptionVectorSize = encryptionSignalByte & 0x7F;
- mEncryptionDataSizeToSubtractFromSampleDataSize =
- mEncryptionVectorSize + 1; // Signal byte.
- mEncryptionDataReadState = STATE_READING_INIT_VECTOR;
- break;
- case STATE_READING_INIT_VECTOR:
- Arrays.fill(mScratchIvSpace, (byte) 0); // Ensure 0-padding.
- data.readBytes(mScratchIvSpace, /* offset= */ 0, mEncryptionVectorSize);
- length -= mEncryptionVectorSize;
- if (mHasSubsampleEncryptionData) {
- mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE;
- } else {
- mSubsampleEncryptionDataSize = 0;
- mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
- }
- break;
- case STATE_READING_SUBSAMPLE_ENCRYPTION_SIZE:
- mSubsampleEncryptionDataSize = data.readUnsignedShort();
- if (mScratchSubsampleClearBytesCount.length
- < mSubsampleEncryptionDataSize) {
- mScratchSubsampleClearBytesCount =
- new int[mSubsampleEncryptionDataSize];
- mScratchSubsampleEncryptedBytesCount =
- new int[mSubsampleEncryptionDataSize];
- }
- length -= 2;
- mEncryptionDataSizeToSubtractFromSampleDataSize +=
- 2
- + mSubsampleEncryptionDataSize
- * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
- mEncryptionDataReadState = STATE_READING_SUBSAMPLE_ENCRYPTION_DATA;
- break;
- case STATE_READING_SUBSAMPLE_ENCRYPTION_DATA:
- for (int i = 0; i < mSubsampleEncryptionDataSize; i++) {
- mScratchSubsampleClearBytesCount[i] = data.readUnsignedShort();
- mScratchSubsampleEncryptedBytesCount[i] = data.readInt();
- }
- length -=
- mSubsampleEncryptionDataSize
- * BYTES_PER_SUBSAMPLE_ENCRYPTION_ENTRY;
- mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
- if (length != 0) {
- throw new IllegalStateException();
- }
- break;
- default:
- // Never happens.
- throw new IllegalStateException();
- }
- }
- } else if (sampleDataPart == SAMPLE_DATA_PART_SUPPLEMENTAL
- && !mIncludeSupplementalData) {
- mSkippedSupplementalDataBytes += length;
- data.skipBytes(length);
- } else {
- outputSampleData(data, length);
- }
- }
-
- @Override
- public void sampleMetadata(
- long timeUs, int flags, int size, int offset, @Nullable CryptoData cryptoData) {
- size -= mSkippedSupplementalDataBytes;
- mSkippedSupplementalDataBytes = 0;
- mOutputConsumer.onSampleCompleted(
- mTrackIndex,
- timeUs,
- getMediaParserFlags(flags),
- size - mEncryptionDataSizeToSubtractFromSampleDataSize,
- offset,
- getPopulatedCryptoInfo(cryptoData));
- mEncryptionDataReadState = STATE_READING_SIGNAL_BYTE;
- mEncryptionDataSizeToSubtractFromSampleDataSize = 0;
- }
-
- @Nullable
- private CryptoInfo getPopulatedCryptoInfo(@Nullable CryptoData cryptoData) {
- if (cryptoData == null) {
- // The sample is not encrypted.
- return null;
- } else if (mInBandCryptoInfo) {
- if (cryptoData != mLastReceivedCryptoData) {
- mLastOutputCryptoInfo =
- createNewCryptoInfoAndPopulateWithCryptoData(cryptoData);
- // We are using in-band crypto info, so the IV will be ignored. But we prevent
- // it from being null because toString assumes it non-null.
- mLastOutputCryptoInfo.iv = EMPTY_BYTE_ARRAY;
- }
- } else /* We must populate the full CryptoInfo. */ {
- // CryptoInfo.pattern is not accessible to the user, so the user needs to feed
- // this CryptoInfo directly to MediaCodec. We need to create a new CryptoInfo per
- // sample because of per-sample initialization vector changes.
- CryptoInfo newCryptoInfo = createNewCryptoInfoAndPopulateWithCryptoData(cryptoData);
- newCryptoInfo.iv = Arrays.copyOf(mScratchIvSpace, mScratchIvSpace.length);
- boolean canReuseSubsampleInfo =
- mLastOutputCryptoInfo != null
- && mLastOutputCryptoInfo.numSubSamples
- == mSubsampleEncryptionDataSize;
- for (int i = 0; i < mSubsampleEncryptionDataSize && canReuseSubsampleInfo; i++) {
- canReuseSubsampleInfo =
- mLastOutputCryptoInfo.numBytesOfClearData[i]
- == mScratchSubsampleClearBytesCount[i]
- && mLastOutputCryptoInfo.numBytesOfEncryptedData[i]
- == mScratchSubsampleEncryptedBytesCount[i];
- }
- newCryptoInfo.numSubSamples = mSubsampleEncryptionDataSize;
- if (canReuseSubsampleInfo) {
- newCryptoInfo.numBytesOfClearData = mLastOutputCryptoInfo.numBytesOfClearData;
- newCryptoInfo.numBytesOfEncryptedData =
- mLastOutputCryptoInfo.numBytesOfEncryptedData;
- } else {
- newCryptoInfo.numBytesOfClearData =
- Arrays.copyOf(
- mScratchSubsampleClearBytesCount, mSubsampleEncryptionDataSize);
- newCryptoInfo.numBytesOfEncryptedData =
- Arrays.copyOf(
- mScratchSubsampleEncryptedBytesCount,
- mSubsampleEncryptionDataSize);
- }
- mLastOutputCryptoInfo = newCryptoInfo;
- }
- mLastReceivedCryptoData = cryptoData;
- return mLastOutputCryptoInfo;
- }
-
- private CryptoInfo createNewCryptoInfoAndPopulateWithCryptoData(CryptoData cryptoData) {
- CryptoInfo cryptoInfo = new CryptoInfo();
- cryptoInfo.key = cryptoData.encryptionKey;
- cryptoInfo.mode = cryptoData.cryptoMode;
- if (cryptoData.clearBlocks != mLastOutputEncryptionPattern.getSkipBlocks()
- || cryptoData.encryptedBlocks
- != mLastOutputEncryptionPattern.getEncryptBlocks()) {
- mLastOutputEncryptionPattern =
- new CryptoInfo.Pattern(cryptoData.encryptedBlocks, cryptoData.clearBlocks);
- }
- cryptoInfo.setPattern(mLastOutputEncryptionPattern);
- return cryptoInfo;
- }
-
- private void outputSampleData(ParsableByteArray data, int length) {
- mScratchParsableByteArrayAdapter.resetWithByteArray(data, length);
- try {
- // Read all bytes from data. ExoPlayer extractors expect all sample data to be
- // consumed by TrackOutput implementations when passing a ParsableByteArray.
- while (mScratchParsableByteArrayAdapter.getLength() > 0) {
- mOutputConsumer.onSampleDataFound(
- mTrackIndex, mScratchParsableByteArrayAdapter);
- }
- } catch (IOException e) {
- // Unexpected.
- throw new RuntimeException(e);
- }
- }
- }
-
- private static final class DataReaderAdapter implements InputReader {
-
- private DataReader mDataReader;
- private int mCurrentPosition;
- private long mLength;
-
- public void setDataReader(DataReader dataReader, long length) {
- mDataReader = dataReader;
- mCurrentPosition = 0;
- mLength = length;
- }
-
- // Input implementation.
-
- @Override
- public int read(byte[] buffer, int offset, int readLength) throws IOException {
- int readBytes = 0;
- readBytes = mDataReader.read(buffer, offset, readLength);
- mCurrentPosition += readBytes;
- return readBytes;
- }
-
- @Override
- public long getPosition() {
- return mCurrentPosition;
- }
-
- @Override
- public long getLength() {
- return mLength - mCurrentPosition;
- }
- }
-
- private static final class ParsableByteArrayAdapter implements InputReader {
-
- private ParsableByteArray mByteArray;
- private long mLength;
- private int mCurrentPosition;
-
- public void resetWithByteArray(ParsableByteArray byteArray, long length) {
- mByteArray = byteArray;
- mCurrentPosition = 0;
- mLength = length;
- }
-
- // Input implementation.
-
- @Override
- public int read(byte[] buffer, int offset, int readLength) {
- mByteArray.readBytes(buffer, offset, readLength);
- mCurrentPosition += readLength;
- return readLength;
- }
-
- @Override
- public long getPosition() {
- return mCurrentPosition;
- }
-
- @Override
- public long getLength() {
- return mLength - mCurrentPosition;
- }
- }
-
- private static final class DummyExoPlayerSeekMap
- implements com.google.android.exoplayer2.extractor.SeekMap {
-
- @Override
- public boolean isSeekable() {
- return true;
- }
-
- @Override
- public long getDurationUs() {
- return C.TIME_UNSET;
- }
-
- @Override
- public SeekPoints getSeekPoints(long timeUs) {
- com.google.android.exoplayer2.extractor.SeekPoint seekPoint =
- new com.google.android.exoplayer2.extractor.SeekPoint(
- timeUs, /* position= */ 0);
- return new SeekPoints(seekPoint, seekPoint);
- }
- }
-
- /** Creates extractor instances. */
- private interface ExtractorFactory {
-
- /** Returns a new extractor instance. */
- Extractor createInstance();
- }
-
- // Private static methods.
-
- private static Format toExoPlayerCaptionFormat(MediaFormat mediaFormat) {
- Format.Builder formatBuilder =
- new Format.Builder().setSampleMimeType(mediaFormat.getString(MediaFormat.KEY_MIME));
- if (mediaFormat.containsKey(MediaFormat.KEY_CAPTION_SERVICE_NUMBER)) {
- formatBuilder.setAccessibilityChannel(
- mediaFormat.getInteger(MediaFormat.KEY_CAPTION_SERVICE_NUMBER));
- }
- return formatBuilder.build();
- }
-
- private static MediaFormat toMediaFormat(Format format) {
- MediaFormat result = new MediaFormat();
- setOptionalMediaFormatInt(result, MediaFormat.KEY_BIT_RATE, format.bitrate);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_CHANNEL_COUNT, format.channelCount);
-
- ColorInfo colorInfo = format.colorInfo;
- if (colorInfo != null) {
- setOptionalMediaFormatInt(
- result, MediaFormat.KEY_COLOR_TRANSFER, colorInfo.colorTransfer);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_COLOR_RANGE, colorInfo.colorRange);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_COLOR_STANDARD, colorInfo.colorSpace);
-
- if (format.colorInfo.hdrStaticInfo != null) {
- result.setByteBuffer(
- MediaFormat.KEY_HDR_STATIC_INFO,
- ByteBuffer.wrap(format.colorInfo.hdrStaticInfo));
- }
- }
-
- setOptionalMediaFormatString(result, MediaFormat.KEY_MIME, format.sampleMimeType);
- setOptionalMediaFormatString(result, MediaFormat.KEY_CODECS_STRING, format.codecs);
- if (format.frameRate != Format.NO_VALUE) {
- result.setFloat(MediaFormat.KEY_FRAME_RATE, format.frameRate);
- }
- setOptionalMediaFormatInt(result, MediaFormat.KEY_WIDTH, format.width);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_HEIGHT, format.height);
-
- List<byte[]> initData = format.initializationData;
- for (int i = 0; i < initData.size(); i++) {
- result.setByteBuffer("csd-" + i, ByteBuffer.wrap(initData.get(i)));
- }
- setPcmEncoding(format, result);
- setOptionalMediaFormatString(result, MediaFormat.KEY_LANGUAGE, format.language);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_ROTATION, format.rotationDegrees);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_SAMPLE_RATE, format.sampleRate);
- setOptionalMediaFormatInt(
- result, MediaFormat.KEY_CAPTION_SERVICE_NUMBER, format.accessibilityChannel);
-
- int selectionFlags = format.selectionFlags;
- result.setInteger(
- MediaFormat.KEY_IS_AUTOSELECT, selectionFlags & C.SELECTION_FLAG_AUTOSELECT);
- result.setInteger(MediaFormat.KEY_IS_DEFAULT, selectionFlags & C.SELECTION_FLAG_DEFAULT);
- result.setInteger(
- MediaFormat.KEY_IS_FORCED_SUBTITLE, selectionFlags & C.SELECTION_FLAG_FORCED);
-
- setOptionalMediaFormatInt(result, MediaFormat.KEY_ENCODER_DELAY, format.encoderDelay);
- setOptionalMediaFormatInt(result, MediaFormat.KEY_ENCODER_PADDING, format.encoderPadding);
-
- if (format.pixelWidthHeightRatio != Format.NO_VALUE && format.pixelWidthHeightRatio != 0) {
- int parWidth = 1;
- int parHeight = 1;
- if (format.pixelWidthHeightRatio < 1.0f) {
- parHeight = 1 << 30;
- parWidth = (int) (format.pixelWidthHeightRatio * parHeight);
- } else if (format.pixelWidthHeightRatio > 1.0f) {
- parWidth = 1 << 30;
- parHeight = (int) (parWidth / format.pixelWidthHeightRatio);
- }
- result.setInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_WIDTH, parWidth);
- result.setInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_HEIGHT, parHeight);
- result.setFloat("pixel-width-height-ratio-float", format.pixelWidthHeightRatio);
- }
- if (format.drmInitData != null) {
- // The crypto mode is propagated along with sample metadata. We also include it in the
- // format for convenient use from ExoPlayer.
- result.setString("crypto-mode-fourcc", format.drmInitData.schemeType);
- }
- if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
- result.setLong("subsample-offset-us-long", format.subsampleOffsetUs);
- }
- // LACK OF SUPPORT FOR:
- // format.id;
- // format.metadata;
- // format.stereoMode;
- return result;
- }
-
- private static ByteBuffer toByteBuffer(long[] longArray) {
- ByteBuffer byteBuffer = ByteBuffer.allocateDirect(longArray.length * Long.BYTES);
- for (long element : longArray) {
- byteBuffer.putLong(element);
- }
- byteBuffer.flip();
- return byteBuffer;
- }
-
- private static ByteBuffer toByteBuffer(int[] intArray) {
- ByteBuffer byteBuffer = ByteBuffer.allocateDirect(intArray.length * Integer.BYTES);
- for (int element : intArray) {
- byteBuffer.putInt(element);
- }
- byteBuffer.flip();
- return byteBuffer;
- }
-
- private static String toTypeString(int type) {
- switch (type) {
- case C.TRACK_TYPE_VIDEO:
- return "video";
- case C.TRACK_TYPE_AUDIO:
- return "audio";
- case C.TRACK_TYPE_TEXT:
- return "text";
- case C.TRACK_TYPE_METADATA:
- return "metadata";
- default:
- return "unknown";
- }
- }
-
- private static void setPcmEncoding(Format format, MediaFormat result) {
- int exoPcmEncoding = format.pcmEncoding;
- setOptionalMediaFormatInt(result, "exo-pcm-encoding", format.pcmEncoding);
- int mediaFormatPcmEncoding;
- switch (exoPcmEncoding) {
- case C.ENCODING_PCM_8BIT:
- mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_8BIT;
- break;
- case C.ENCODING_PCM_16BIT:
- mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_16BIT;
- break;
- case C.ENCODING_PCM_FLOAT:
- mediaFormatPcmEncoding = AudioFormat.ENCODING_PCM_FLOAT;
- break;
- default:
- // No matching value. Do nothing.
- return;
- }
- result.setInteger(MediaFormat.KEY_PCM_ENCODING, mediaFormatPcmEncoding);
- }
-
- private static void setOptionalMediaFormatInt(MediaFormat mediaFormat, String key, int value) {
- if (value != Format.NO_VALUE) {
- mediaFormat.setInteger(key, value);
- }
- }
-
- private static void setOptionalMediaFormatString(
- MediaFormat mediaFormat, String key, @Nullable String value) {
- if (value != null) {
- mediaFormat.setString(key, value);
- }
- }
-
- private DrmInitData toFrameworkDrmInitData(
- com.google.android.exoplayer2.drm.DrmInitData exoDrmInitData) {
- try {
- return exoDrmInitData != null && mSchemeInitDataConstructor != null
- ? new MediaParserDrmInitData(exoDrmInitData)
- : null;
- } catch (Throwable e) {
- if (!mLoggedSchemeInitDataCreationException) {
- mLoggedSchemeInitDataCreationException = true;
- Log.e(TAG, "Unable to create SchemeInitData instance.");
- }
- return null;
- }
- }
-
- /** Returns a new {@link SeekPoint} equivalent to the given {@code exoPlayerSeekPoint}. */
- private static SeekPoint toSeekPoint(
- com.google.android.exoplayer2.extractor.SeekPoint exoPlayerSeekPoint) {
- return new SeekPoint(exoPlayerSeekPoint.timeUs, exoPlayerSeekPoint.position);
- }
-
- /**
- * Introduces random error to the given metric value in order to prevent the identification of
- * the parsed media.
- */
- private static long addDither(long value) {
- // Generate a random in [0, 1].
- double randomDither = ThreadLocalRandom.current().nextFloat();
- // Clamp the random number to [0, 2 * MEDIAMETRICS_DITHER].
- randomDither *= 2 * MEDIAMETRICS_DITHER;
- // Translate the random number to [1 - MEDIAMETRICS_DITHER, 1 + MEDIAMETRICS_DITHER].
- randomDither += 1 - MEDIAMETRICS_DITHER;
- return value != -1 ? (long) (value * randomDither) : -1;
- }
-
- private static void assertValidNames(@NonNull String[] names) {
- for (String name : names) {
- if (!EXTRACTOR_FACTORIES_BY_NAME.containsKey(name)) {
- throw new IllegalArgumentException(
- "Invalid extractor name: "
- + name
- + ". Supported parsers are: "
- + TextUtils.join(", ", EXTRACTOR_FACTORIES_BY_NAME.keySet())
- + ".");
- }
- }
- }
-
- private int getMediaParserFlags(int flags) {
- @SampleFlags int result = 0;
- result |= (flags & C.BUFFER_FLAG_ENCRYPTED) != 0 ? SAMPLE_FLAG_ENCRYPTED : 0;
- result |= (flags & C.BUFFER_FLAG_KEY_FRAME) != 0 ? SAMPLE_FLAG_KEY_FRAME : 0;
- result |= (flags & C.BUFFER_FLAG_DECODE_ONLY) != 0 ? SAMPLE_FLAG_DECODE_ONLY : 0;
- result |=
- (flags & C.BUFFER_FLAG_HAS_SUPPLEMENTAL_DATA) != 0 && mIncludeSupplementalData
- ? SAMPLE_FLAG_HAS_SUPPLEMENTAL_DATA
- : 0;
- result |= (flags & C.BUFFER_FLAG_LAST_SAMPLE) != 0 ? SAMPLE_FLAG_LAST_SAMPLE : 0;
- return result;
- }
-
- @Nullable
- private static Constructor<DrmInitData.SchemeInitData> getSchemeInitDataConstructor() {
- // TODO: Use constructor statically when available.
- Constructor<DrmInitData.SchemeInitData> constructor;
- try {
- return DrmInitData.SchemeInitData.class.getConstructor(
- UUID.class, String.class, byte[].class);
- } catch (Throwable e) {
- Log.e(TAG, "Unable to get SchemeInitData constructor.");
- return null;
- }
- }
-
- // Native methods.
-
- private native void nativeSubmitMetrics(
- String logSessionId,
- String parserName,
- boolean createdByName,
- String parserPool,
- String lastObservedExceptionName,
- long resourceByteCount,
- long durationMillis,
- String trackMimeTypes,
- String trackCodecs,
- String alteredParameters,
- int videoWidth,
- int videoHeight);
-
- // Static initialization.
-
- static {
- System.loadLibrary(JNI_LIBRARY_NAME);
-
- // Using a LinkedHashMap to keep the insertion order when iterating over the keys.
- LinkedHashMap<String, ExtractorFactory> extractorFactoriesByName = new LinkedHashMap<>();
- // Parsers are ordered to match ExoPlayer's DefaultExtractorsFactory extractor ordering,
- // which in turn aims to minimize the chances of incorrect extractor selections.
- extractorFactoriesByName.put(PARSER_NAME_MATROSKA, MatroskaExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_FMP4, FragmentedMp4Extractor::new);
- extractorFactoriesByName.put(PARSER_NAME_MP4, Mp4Extractor::new);
- extractorFactoriesByName.put(PARSER_NAME_MP3, Mp3Extractor::new);
- extractorFactoriesByName.put(PARSER_NAME_ADTS, AdtsExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_AC3, Ac3Extractor::new);
- extractorFactoriesByName.put(PARSER_NAME_TS, TsExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_FLV, FlvExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_OGG, OggExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_PS, PsExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_WAV, WavExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_AMR, AmrExtractor::new);
- extractorFactoriesByName.put(PARSER_NAME_AC4, Ac4Extractor::new);
- extractorFactoriesByName.put(PARSER_NAME_FLAC, FlacExtractor::new);
- EXTRACTOR_FACTORIES_BY_NAME = Collections.unmodifiableMap(extractorFactoriesByName);
-
- HashMap<String, Class> expectedTypeByParameterName = new HashMap<>();
- expectedTypeByParameterName.put(PARAMETER_ADTS_ENABLE_CBR_SEEKING, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_AMR_ENABLE_CBR_SEEKING, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_FLAC_DISABLE_ID3, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_EDIT_LISTS, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_TFDT_BOX, Boolean.class);
- expectedTypeByParameterName.put(
- PARAMETER_MP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_MP3_DISABLE_ID3, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_CBR_SEEKING, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_INDEX_SEEKING, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_TS_MODE, String.class);
- expectedTypeByParameterName.put(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_AAC_STREAM, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_AVC_STREAM, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_TS_DETECT_ACCESS_UNITS, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_IN_BAND_CRYPTO_INFO, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_INCLUDE_SUPPLEMENTAL_DATA, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_IGNORE_TIMESTAMP_OFFSET, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_EAGERLY_EXPOSE_TRACKTYPE, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_EXPOSE_DUMMY_SEEKMAP, Boolean.class);
- expectedTypeByParameterName.put(
- PARAMETER_EXPOSE_CHUNK_INDEX_AS_MEDIA_FORMAT, Boolean.class);
- expectedTypeByParameterName.put(
- PARAMETER_OVERRIDE_IN_BAND_CAPTION_DECLARATIONS, Boolean.class);
- expectedTypeByParameterName.put(PARAMETER_EXPOSE_EMSG_TRACK, Boolean.class);
- // We do not check PARAMETER_EXPOSE_CAPTION_FORMATS here, and we do it in setParameters
- // instead. Checking that the value is a List is insufficient to catch wrong parameter
- // value types.
- int sumOfParameterNameLengths =
- expectedTypeByParameterName.keySet().stream()
- .map(String::length)
- .reduce(0, Integer::sum);
- sumOfParameterNameLengths += PARAMETER_EXPOSE_CAPTION_FORMATS.length();
- // Add space for any required separators.
- MEDIAMETRICS_PARAMETER_LIST_MAX_LENGTH =
- sumOfParameterNameLengths + expectedTypeByParameterName.size();
-
- EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaSession2.java b/apex/media/framework/java/android/media/MediaSession2.java
deleted file mode 100644
index e76d61c..0000000
--- a/apex/media/framework/java/android/media/MediaSession2.java
+++ /dev/null
@@ -1,931 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS;
-import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
-import static android.media.MediaConstants.KEY_PACKAGE_NAME;
-import static android.media.MediaConstants.KEY_PID;
-import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE;
-import static android.media.MediaConstants.KEY_SESSION2LINK;
-import static android.media.MediaConstants.KEY_TOKEN_EXTRAS;
-import static android.media.Session2Command.Result.RESULT_ERROR_UNKNOWN_ERROR;
-import static android.media.Session2Command.Result.RESULT_INFO_SKIPPED;
-import static android.media.Session2Token.TYPE_SESSION;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.media.session.MediaSessionManager;
-import android.media.session.MediaSessionManager.RemoteUserInfo;
-import android.os.BadParcelableException;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Process;
-import android.os.ResultReceiver;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.modules.utils.build.SdkLevel;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Allows a media app to expose its transport controls and playback information in a process to
- * other processes including the Android framework and other apps.
- */
-public class MediaSession2 implements AutoCloseable {
- static final String TAG = "MediaSession2";
- static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- // Note: This checks the uniqueness of a session ID only in a single process.
- // When the framework becomes able to check the uniqueness, this logic should be removed.
- //@GuardedBy("MediaSession.class")
- private static final List<String> SESSION_ID_LIST = new ArrayList<>();
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final Object mLock = new Object();
- //@GuardedBy("mLock")
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final Map<Controller2Link, ControllerInfo> mConnectedControllers = new HashMap<>();
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final Context mContext;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final Executor mCallbackExecutor;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final SessionCallback mCallback;
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- final Session2Link mSessionStub;
-
- private final String mSessionId;
- private final PendingIntent mSessionActivity;
- private final Session2Token mSessionToken;
- private final MediaSessionManager mMediaSessionManager;
- private final MediaCommunicationManager mCommunicationManager;
- private final Handler mResultHandler;
-
- //@GuardedBy("mLock")
- private boolean mClosed;
- //@GuardedBy("mLock")
- private boolean mPlaybackActive;
- //@GuardedBy("mLock")
- private ForegroundServiceEventCallback mForegroundServiceEventCallback;
-
- MediaSession2(@NonNull Context context, @NonNull String id, PendingIntent sessionActivity,
- @NonNull Executor callbackExecutor, @NonNull SessionCallback callback,
- @NonNull Bundle tokenExtras) {
- synchronized (MediaSession2.class) {
- if (SESSION_ID_LIST.contains(id)) {
- throw new IllegalStateException("Session ID must be unique. ID=" + id);
- }
- SESSION_ID_LIST.add(id);
- }
-
- mContext = context;
- mSessionId = id;
- mSessionActivity = sessionActivity;
- mCallbackExecutor = callbackExecutor;
- mCallback = callback;
- mSessionStub = new Session2Link(this);
- mSessionToken = new Session2Token(Process.myUid(), TYPE_SESSION, context.getPackageName(),
- mSessionStub, tokenExtras);
- if (SdkLevel.isAtLeastS()) {
- mCommunicationManager = mContext.getSystemService(MediaCommunicationManager.class);
- mMediaSessionManager = null;
- } else {
- mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class);
- mCommunicationManager = null;
- }
- // NOTE: mResultHandler uses main looper, so this MUST NOT be blocked.
- mResultHandler = new Handler(context.getMainLooper());
- mClosed = false;
- }
-
- @Override
- public void close() {
- try {
- List<ControllerInfo> controllerInfos;
- ForegroundServiceEventCallback callback;
- synchronized (mLock) {
- if (mClosed) {
- return;
- }
- mClosed = true;
- controllerInfos = getConnectedControllers();
- mConnectedControllers.clear();
- callback = mForegroundServiceEventCallback;
- mForegroundServiceEventCallback = null;
- }
- synchronized (MediaSession2.class) {
- SESSION_ID_LIST.remove(mSessionId);
- }
- if (callback != null) {
- callback.onSessionClosed(this);
- }
- for (ControllerInfo info : controllerInfos) {
- info.notifyDisconnected();
- }
- } catch (Exception e) {
- // Should not be here.
- }
- }
-
- /**
- * Returns the session ID
- */
- @NonNull
- public String getId() {
- return mSessionId;
- }
-
- /**
- * Returns the {@link Session2Token} for creating {@link MediaController2}.
- */
- @NonNull
- public Session2Token getToken() {
- return mSessionToken;
- }
-
- /**
- * Broadcasts a session command to all the connected controllers
- * <p>
- * @param command the session command
- * @param args optional arguments
- */
- public void broadcastSessionCommand(@NonNull Session2Command command, @Nullable Bundle args) {
- if (command == null) {
- throw new IllegalArgumentException("command shouldn't be null");
- }
- List<ControllerInfo> controllerInfos = getConnectedControllers();
- for (ControllerInfo controller : controllerInfos) {
- controller.sendSessionCommand(command, args, null);
- }
- }
-
- /**
- * Sends a session command to a specific controller
- * <p>
- * @param controller the controller to get the session command
- * @param command the session command
- * @param args optional arguments
- * @return a token which will be sent together in {@link SessionCallback#onCommandResult}
- * when its result is received.
- */
- @NonNull
- public Object sendSessionCommand(@NonNull ControllerInfo controller,
- @NonNull Session2Command command, @Nullable Bundle args) {
- if (controller == null) {
- throw new IllegalArgumentException("controller shouldn't be null");
- }
- if (command == null) {
- throw new IllegalArgumentException("command shouldn't be null");
- }
- ResultReceiver resultReceiver = new ResultReceiver(mResultHandler) {
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- controller.receiveCommandResult(this);
- mCallbackExecutor.execute(() -> {
- mCallback.onCommandResult(MediaSession2.this, controller, this,
- command, new Session2Command.Result(resultCode, resultData));
- });
- }
- };
- controller.sendSessionCommand(command, args, resultReceiver);
- return resultReceiver;
- }
-
- /**
- * Cancels the session command previously sent.
- *
- * @param controller the controller to get the session command
- * @param token the token which is returned from {@link #sendSessionCommand}.
- */
- public void cancelSessionCommand(@NonNull ControllerInfo controller, @NonNull Object token) {
- if (controller == null) {
- throw new IllegalArgumentException("controller shouldn't be null");
- }
- if (token == null) {
- throw new IllegalArgumentException("token shouldn't be null");
- }
- controller.cancelSessionCommand(token);
- }
-
- /**
- * Sets whether the playback is active (i.e. playing something)
- *
- * @param playbackActive {@code true} if the playback active, {@code false} otherwise.
- **/
- public void setPlaybackActive(boolean playbackActive) {
- final ForegroundServiceEventCallback serviceCallback;
- synchronized (mLock) {
- if (mPlaybackActive == playbackActive) {
- return;
- }
- mPlaybackActive = playbackActive;
- serviceCallback = mForegroundServiceEventCallback;
- }
- if (serviceCallback != null) {
- serviceCallback.onPlaybackActiveChanged(this, playbackActive);
- }
- List<ControllerInfo> controllerInfos = getConnectedControllers();
- for (ControllerInfo controller : controllerInfos) {
- controller.notifyPlaybackActiveChanged(playbackActive);
- }
- }
-
- /**
- * Returns whehther the playback is active (i.e. playing something)
- *
- * @return {@code true} if the playback active, {@code false} otherwise.
- */
- public boolean isPlaybackActive() {
- synchronized (mLock) {
- return mPlaybackActive;
- }
- }
-
- /**
- * Gets the list of the connected controllers
- *
- * @return list of the connected controllers.
- */
- @NonNull
- public List<ControllerInfo> getConnectedControllers() {
- List<ControllerInfo> controllers = new ArrayList<>();
- synchronized (mLock) {
- controllers.addAll(mConnectedControllers.values());
- }
- return controllers;
- }
-
- /**
- * Returns whether the given bundle includes non-framework Parcelables.
- */
- static boolean hasCustomParcelable(@Nullable Bundle bundle) {
- if (bundle == null) {
- return false;
- }
-
- // Try writing the bundle to parcel, and read it with framework classloader.
- Parcel parcel = null;
- try {
- parcel = Parcel.obtain();
- parcel.writeBundle(bundle);
- parcel.setDataPosition(0);
- Bundle out = parcel.readBundle(null);
-
- // Calling Bundle#size() will trigger Bundle#unparcel().
- out.size();
- } catch (BadParcelableException e) {
- Log.d(TAG, "Custom parcelable in bundle.", e);
- return true;
- } finally {
- if (parcel != null) {
- parcel.recycle();
- }
- }
- return false;
- }
-
- boolean isClosed() {
- synchronized (mLock) {
- return mClosed;
- }
- }
-
- SessionCallback getCallback() {
- return mCallback;
- }
-
- boolean isTrustedForMediaControl(RemoteUserInfo remoteUserInfo) {
- if (SdkLevel.isAtLeastS()) {
- return mCommunicationManager.isTrustedForMediaControl(remoteUserInfo);
- } else {
- return mMediaSessionManager.isTrustedForMediaControl(remoteUserInfo);
- }
- }
-
- void setForegroundServiceEventCallback(ForegroundServiceEventCallback callback) {
- synchronized (mLock) {
- if (mForegroundServiceEventCallback == callback) {
- return;
- }
- if (mForegroundServiceEventCallback != null && callback != null) {
- throw new IllegalStateException("A session cannot be added to multiple services");
- }
- mForegroundServiceEventCallback = callback;
- }
- }
-
- // Called by Session2Link.onConnect and MediaSession2Service.MediaSession2ServiceStub.connect
- void onConnect(final Controller2Link controller, int callingPid, int callingUid, int seq,
- Bundle connectionRequest) {
- if (callingPid == 0) {
- // The pid here is from Binder.getCallingPid(), which can be 0 for an oneway call from
- // the remote process. If it's the case, use PID from the connectionRequest.
- callingPid = connectionRequest.getInt(KEY_PID);
- }
- String callingPkg = connectionRequest.getString(KEY_PACKAGE_NAME);
-
- RemoteUserInfo remoteUserInfo = new RemoteUserInfo(callingPkg, callingPid, callingUid);
-
- Bundle connectionHints = connectionRequest.getBundle(KEY_CONNECTION_HINTS);
- if (connectionHints == null) {
- Log.w(TAG, "connectionHints shouldn't be null.");
- connectionHints = Bundle.EMPTY;
- } else if (hasCustomParcelable(connectionHints)) {
- Log.w(TAG, "connectionHints contain custom parcelable. Ignoring.");
- connectionHints = Bundle.EMPTY;
- }
-
- final ControllerInfo controllerInfo = new ControllerInfo(
- remoteUserInfo,
- isTrustedForMediaControl(remoteUserInfo),
- controller,
- connectionHints);
- mCallbackExecutor.execute(() -> {
- boolean connected = false;
- try {
- if (isClosed()) {
- return;
- }
- controllerInfo.mAllowedCommands =
- mCallback.onConnect(MediaSession2.this, controllerInfo);
- // Don't reject connection for the request from trusted app.
- // Otherwise server will fail to retrieve session's information to dispatch
- // media keys to.
- if (controllerInfo.mAllowedCommands == null && !controllerInfo.isTrusted()) {
- return;
- }
- if (controllerInfo.mAllowedCommands == null) {
- // For trusted apps, send non-null allowed commands to keep
- // connection.
- controllerInfo.mAllowedCommands =
- new Session2CommandGroup.Builder().build();
- }
- if (DEBUG) {
- Log.d(TAG, "Accepting connection: " + controllerInfo);
- }
- // If connection is accepted, notify the current state to the controller.
- // It's needed because we cannot call synchronous calls between
- // session/controller.
- Bundle connectionResult = new Bundle();
- connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub);
- connectionResult.putParcelable(KEY_ALLOWED_COMMANDS,
- controllerInfo.mAllowedCommands);
- connectionResult.putBoolean(KEY_PLAYBACK_ACTIVE, isPlaybackActive());
- connectionResult.putBundle(KEY_TOKEN_EXTRAS, mSessionToken.getExtras());
-
- // Double check if session is still there, because close() can be called in
- // another thread.
- if (isClosed()) {
- return;
- }
- controllerInfo.notifyConnected(connectionResult);
- synchronized (mLock) {
- if (mConnectedControllers.containsKey(controller)) {
- Log.w(TAG, "Controller " + controllerInfo + " has sent connection"
- + " request multiple times");
- }
- mConnectedControllers.put(controller, controllerInfo);
- }
- mCallback.onPostConnect(MediaSession2.this, controllerInfo);
- connected = true;
- } finally {
- if (!connected || isClosed()) {
- if (DEBUG) {
- Log.d(TAG, "Rejecting connection or notifying that session is closed"
- + ", controllerInfo=" + controllerInfo);
- }
- synchronized (mLock) {
- mConnectedControllers.remove(controller);
- }
- controllerInfo.notifyDisconnected();
- }
- }
- });
- }
-
- // Called by Session2Link.onDisconnect
- void onDisconnect(@NonNull final Controller2Link controller, int seq) {
- final ControllerInfo controllerInfo;
- synchronized (mLock) {
- controllerInfo = mConnectedControllers.remove(controller);
- }
- if (controllerInfo == null) {
- return;
- }
- mCallbackExecutor.execute(() -> {
- mCallback.onDisconnected(MediaSession2.this, controllerInfo);
- });
- }
-
- // Called by Session2Link.onSessionCommand
- void onSessionCommand(@NonNull final Controller2Link controller, final int seq,
- final Session2Command command, final Bundle args,
- @Nullable ResultReceiver resultReceiver) {
- if (controller == null) {
- return;
- }
- final ControllerInfo controllerInfo;
- synchronized (mLock) {
- controllerInfo = mConnectedControllers.get(controller);
- }
- if (controllerInfo == null) {
- return;
- }
-
- // TODO: check allowed commands.
- synchronized (mLock) {
- controllerInfo.addRequestedCommandSeqNumber(seq);
- }
- mCallbackExecutor.execute(() -> {
- if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) {
- if (resultReceiver != null) {
- resultReceiver.send(RESULT_INFO_SKIPPED, null);
- }
- return;
- }
- Session2Command.Result result = mCallback.onSessionCommand(
- MediaSession2.this, controllerInfo, command, args);
- if (resultReceiver != null) {
- if (result == null) {
- resultReceiver.send(RESULT_INFO_SKIPPED, null);
- } else {
- resultReceiver.send(result.getResultCode(), result.getResultData());
- }
- }
- });
- }
-
- // Called by Session2Link.onCancelCommand
- void onCancelCommand(@NonNull final Controller2Link controller, final int seq) {
- final ControllerInfo controllerInfo;
- synchronized (mLock) {
- controllerInfo = mConnectedControllers.get(controller);
- }
- if (controllerInfo == null) {
- return;
- }
- controllerInfo.removeRequestedCommandSeqNumber(seq);
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Builder for {@link MediaSession2}.
- * <p>
- * Any incoming event from the {@link MediaController2} will be handled on the callback
- * executor. If it's not set, {@link Context#getMainExecutor()} will be used by default.
- */
- public static final class Builder {
- private Context mContext;
- private String mId;
- private PendingIntent mSessionActivity;
- private Executor mCallbackExecutor;
- private SessionCallback mCallback;
- private Bundle mExtras;
-
- /**
- * Creates a builder for {@link MediaSession2}.
- *
- * @param context Context
- * @throws IllegalArgumentException if context is {@code null}.
- */
- public Builder(@NonNull Context context) {
- if (context == null) {
- throw new IllegalArgumentException("context shouldn't be null");
- }
- mContext = context;
- }
-
- /**
- * Set an intent for launching UI for this Session. This can be used as a
- * quick link to an ongoing media screen. The intent should be for an
- * activity that may be started using {@link Context#startActivity(Intent)}.
- *
- * @param pi The intent to launch to show UI for this session.
- * @return The Builder to allow chaining
- */
- @NonNull
- public Builder setSessionActivity(@Nullable PendingIntent pi) {
- mSessionActivity = pi;
- return this;
- }
-
- /**
- * Set ID of the session. If it's not set, an empty string will be used to create a session.
- * <p>
- * Use this if and only if your app supports multiple playback at the same time and also
- * wants to provide external apps to have finer controls of them.
- *
- * @param id id of the session. Must be unique per package.
- * @throws IllegalArgumentException if id is {@code null}.
- * @return The Builder to allow chaining
- */
- @NonNull
- public Builder setId(@NonNull String id) {
- if (id == null) {
- throw new IllegalArgumentException("id shouldn't be null");
- }
- mId = id;
- return this;
- }
-
- /**
- * Set callback for the session and its executor.
- *
- * @param executor callback executor
- * @param callback session callback.
- * @return The Builder to allow chaining
- */
- @NonNull
- public Builder setSessionCallback(@NonNull Executor executor,
- @NonNull SessionCallback callback) {
- mCallbackExecutor = executor;
- mCallback = callback;
- return this;
- }
-
- /**
- * Set extras for the session token. If null or not set, {@link Session2Token#getExtras()}
- * will return an empty {@link Bundle}. An {@link IllegalArgumentException} will be thrown
- * if the bundle contains any non-framework Parcelable objects.
- *
- * @return The Builder to allow chaining
- * @see Session2Token#getExtras()
- */
- @NonNull
- public Builder setExtras(@NonNull Bundle extras) {
- if (extras == null) {
- throw new NullPointerException("extras shouldn't be null");
- }
- if (hasCustomParcelable(extras)) {
- throw new IllegalArgumentException(
- "extras shouldn't contain any custom parcelables");
- }
- mExtras = new Bundle(extras);
- return this;
- }
-
- /**
- * Build {@link MediaSession2}.
- *
- * @return a new session
- * @throws IllegalStateException if the session with the same id is already exists for the
- * package.
- */
- @NonNull
- public MediaSession2 build() {
- if (mCallbackExecutor == null) {
- mCallbackExecutor = mContext.getMainExecutor();
- }
- if (mCallback == null) {
- mCallback = new SessionCallback() {};
- }
- if (mId == null) {
- mId = "";
- }
- if (mExtras == null) {
- mExtras = Bundle.EMPTY;
- }
- MediaSession2 session2 = new MediaSession2(mContext, mId, mSessionActivity,
- mCallbackExecutor, mCallback, mExtras);
-
- // Notify framework about the newly create session after the constructor is finished.
- // Otherwise, framework may access the session before the initialization is finished.
- try {
- if (SdkLevel.isAtLeastS()) {
- MediaCommunicationManager manager =
- mContext.getSystemService(MediaCommunicationManager.class);
- manager.notifySession2Created(session2.getToken());
- } else {
- MediaSessionManager manager =
- mContext.getSystemService(MediaSessionManager.class);
- manager.notifySession2Created(session2.getToken());
- }
- } catch (Exception e) {
- session2.close();
- throw e;
- }
-
- return session2;
- }
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Information of a controller.
- */
- public static final class ControllerInfo {
- private final RemoteUserInfo mRemoteUserInfo;
- private final boolean mIsTrusted;
- private final Controller2Link mControllerBinder;
- private final Bundle mConnectionHints;
- private final Object mLock = new Object();
- //@GuardedBy("mLock")
- private int mNextSeqNumber;
- //@GuardedBy("mLock")
- private ArrayMap<ResultReceiver, Integer> mPendingCommands;
- //@GuardedBy("mLock")
- private ArraySet<Integer> mRequestedCommandSeqNumbers;
-
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- Session2CommandGroup mAllowedCommands;
-
- /**
- * @param remoteUserInfo remote user info
- * @param trusted {@code true} if trusted, {@code false} otherwise
- * @param controllerBinder Controller2Link for the connected controller.
- * @param connectionHints a session-specific argument sent from the controller for the
- * connection. The contents of this bundle may affect the
- * connection result.
- */
- ControllerInfo(@NonNull RemoteUserInfo remoteUserInfo, boolean trusted,
- @Nullable Controller2Link controllerBinder, @NonNull Bundle connectionHints) {
- mRemoteUserInfo = remoteUserInfo;
- mIsTrusted = trusted;
- mControllerBinder = controllerBinder;
- mConnectionHints = connectionHints;
- mPendingCommands = new ArrayMap<>();
- mRequestedCommandSeqNumbers = new ArraySet<>();
- }
-
- /**
- * @return remote user info of the controller.
- */
- @NonNull
- public RemoteUserInfo getRemoteUserInfo() {
- return mRemoteUserInfo;
- }
-
- /**
- * @return package name of the controller.
- */
- @NonNull
- public String getPackageName() {
- return mRemoteUserInfo.getPackageName();
- }
-
- /**
- * @return uid of the controller. Can be a negative value if the uid cannot be obtained.
- */
- public int getUid() {
- return mRemoteUserInfo.getUid();
- }
-
- /**
- * @return connection hints sent from controller.
- */
- @NonNull
- public Bundle getConnectionHints() {
- return new Bundle(mConnectionHints);
- }
-
- /**
- * Return if the controller has granted {@code android.permission.MEDIA_CONTENT_CONTROL} or
- * has a enabled notification listener so can be trusted to accept connection and incoming
- * command request.
- *
- * @return {@code true} if the controller is trusted.
- * @hide
- */
- public boolean isTrusted() {
- return mIsTrusted;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mControllerBinder, mRemoteUserInfo);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (!(obj instanceof ControllerInfo)) return false;
- if (this == obj) return true;
-
- ControllerInfo other = (ControllerInfo) obj;
- if (mControllerBinder != null || other.mControllerBinder != null) {
- return Objects.equals(mControllerBinder, other.mControllerBinder);
- }
- return mRemoteUserInfo.equals(other.mRemoteUserInfo);
- }
-
- @Override
- @NonNull
- public String toString() {
- return "ControllerInfo {pkg=" + mRemoteUserInfo.getPackageName() + ", uid="
- + mRemoteUserInfo.getUid() + ", allowedCommands=" + mAllowedCommands + "})";
- }
-
- void notifyConnected(Bundle connectionResult) {
- if (mControllerBinder == null) return;
-
- try {
- mControllerBinder.notifyConnected(getNextSeqNumber(), connectionResult);
- } catch (RuntimeException e) {
- // Controller may be died prematurely.
- }
- }
-
- void notifyDisconnected() {
- if (mControllerBinder == null) return;
-
- try {
- mControllerBinder.notifyDisconnected(getNextSeqNumber());
- } catch (RuntimeException e) {
- // Controller may be died prematurely.
- }
- }
-
- void notifyPlaybackActiveChanged(boolean playbackActive) {
- if (mControllerBinder == null) return;
-
- try {
- mControllerBinder.notifyPlaybackActiveChanged(getNextSeqNumber(), playbackActive);
- } catch (RuntimeException e) {
- // Controller may be died prematurely.
- }
- }
-
- void sendSessionCommand(Session2Command command, Bundle args,
- ResultReceiver resultReceiver) {
- if (mControllerBinder == null) return;
-
- try {
- int seq = getNextSeqNumber();
- synchronized (mLock) {
- mPendingCommands.put(resultReceiver, seq);
- }
- mControllerBinder.sendSessionCommand(seq, command, args, resultReceiver);
- } catch (RuntimeException e) {
- // Controller may be died prematurely.
- synchronized (mLock) {
- mPendingCommands.remove(resultReceiver);
- }
- resultReceiver.send(RESULT_ERROR_UNKNOWN_ERROR, null);
- }
- }
-
- void cancelSessionCommand(@NonNull Object token) {
- if (mControllerBinder == null) return;
- Integer seq;
- synchronized (mLock) {
- seq = mPendingCommands.remove(token);
- }
- if (seq != null) {
- mControllerBinder.cancelSessionCommand(seq);
- }
- }
-
- void receiveCommandResult(ResultReceiver resultReceiver) {
- synchronized (mLock) {
- mPendingCommands.remove(resultReceiver);
- }
- }
-
- void addRequestedCommandSeqNumber(int seq) {
- synchronized (mLock) {
- mRequestedCommandSeqNumbers.add(seq);
- }
- }
-
- boolean removeRequestedCommandSeqNumber(int seq) {
- synchronized (mLock) {
- return mRequestedCommandSeqNumbers.remove(seq);
- }
- }
-
- private int getNextSeqNumber() {
- synchronized (mLock) {
- return mNextSeqNumber++;
- }
- }
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Callback to be called for all incoming commands from {@link MediaController2}s.
- */
- public abstract static class SessionCallback {
- /**
- * Called when a controller is created for this session. Return allowed commands for
- * controller. By default it returns {@code null}.
- * <p>
- * You can reject the connection by returning {@code null}. In that case, controller
- * receives {@link MediaController2.ControllerCallback#onDisconnected(MediaController2)}
- * and cannot be used.
- * <p>
- * The controller hasn't connected yet in this method, so calls to the controller
- * (e.g. {@link #sendSessionCommand}) would be ignored. Override {@link #onPostConnect} for
- * the custom initialization for the controller instead.
- *
- * @param session the session for this event
- * @param controller controller information.
- * @return allowed commands. Can be {@code null} to reject connection.
- */
- @Nullable
- public Session2CommandGroup onConnect(@NonNull MediaSession2 session,
- @NonNull ControllerInfo controller) {
- return null;
- }
-
- /**
- * Called immediately after a controller is connected. This is a convenient method to add
- * custom initialization between the session and a controller.
- * <p>
- * Note that calls to the controller (e.g. {@link #sendSessionCommand}) work here but don't
- * work in {@link #onConnect} because the controller hasn't connected yet in
- * {@link #onConnect}.
- *
- * @param session the session for this event
- * @param controller controller information.
- */
- public void onPostConnect(@NonNull MediaSession2 session,
- @NonNull ControllerInfo controller) {
- }
-
- /**
- * Called when a controller is disconnected
- *
- * @param session the session for this event
- * @param controller controller information
- */
- public void onDisconnected(@NonNull MediaSession2 session,
- @NonNull ControllerInfo controller) {}
-
- /**
- * Called when a controller sent a session command.
- *
- * @param session the session for this event
- * @param controller controller information
- * @param command the session command
- * @param args optional arguments
- * @return the result for the session command. If {@code null}, RESULT_INFO_SKIPPED
- * will be sent to the session.
- */
- @Nullable
- public Session2Command.Result onSessionCommand(@NonNull MediaSession2 session,
- @NonNull ControllerInfo controller, @NonNull Session2Command command,
- @Nullable Bundle args) {
- return null;
- }
-
- /**
- * Called when the command sent to the controller is finished.
- *
- * @param session the session for this event
- * @param controller controller information
- * @param token the token got from {@link MediaSession2#sendSessionCommand}
- * @param command the session command
- * @param result the result of the session command
- */
- public void onCommandResult(@NonNull MediaSession2 session,
- @NonNull ControllerInfo controller, @NonNull Object token,
- @NonNull Session2Command command, @NonNull Session2Command.Result result) {}
- }
-
- abstract static class ForegroundServiceEventCallback {
- public void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {}
- public void onSessionClosed(MediaSession2 session) {}
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaSession2Service.java b/apex/media/framework/java/android/media/MediaSession2Service.java
deleted file mode 100644
index f6fd509..0000000
--- a/apex/media/framework/java/android/media/MediaSession2Service.java
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import static android.media.MediaConstants.KEY_CONNECTION_HINTS;
-import static android.media.MediaConstants.KEY_PACKAGE_NAME;
-import static android.media.MediaConstants.KEY_PID;
-
-import android.annotation.CallSuper;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.media.MediaSession2.ControllerInfo;
-import android.media.session.MediaSessionManager;
-import android.media.session.MediaSessionManager.RemoteUserInfo;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Service containing {@link MediaSession2}.
- */
-public abstract class MediaSession2Service extends Service {
- /**
- * The {@link Intent} that must be declared as handled by the service.
- */
- public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service";
-
- private static final String TAG = "MediaSession2Service";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private final MediaSession2.ForegroundServiceEventCallback mForegroundServiceEventCallback =
- new MediaSession2.ForegroundServiceEventCallback() {
- @Override
- public void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {
- MediaSession2Service.this.onPlaybackActiveChanged(session, playbackActive);
- }
-
- @Override
- public void onSessionClosed(MediaSession2 session) {
- removeSession(session);
- }
- };
-
- private final Object mLock = new Object();
- //@GuardedBy("mLock")
- private NotificationManager mNotificationManager;
- //@GuardedBy("mLock")
- private MediaSessionManager mMediaSessionManager;
- //@GuardedBy("mLock")
- private Intent mStartSelfIntent;
- //@GuardedBy("mLock")
- private Map<String, MediaSession2> mSessions = new ArrayMap<>();
- //@GuardedBy("mLock")
- private Map<MediaSession2, MediaNotification> mNotifications = new ArrayMap<>();
- //@GuardedBy("mLock")
- private MediaSession2ServiceStub mStub;
-
- /**
- * Called by the system when the service is first created. Do not call this method directly.
- * <p>
- * Override this method if you need your own initialization. Derived classes MUST call through
- * to the super class's implementation of this method.
- */
- @CallSuper
- @Override
- public void onCreate() {
- super.onCreate();
- synchronized (mLock) {
- mStub = new MediaSession2ServiceStub(this);
- mStartSelfIntent = new Intent(this, this.getClass());
- mNotificationManager =
- (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- mMediaSessionManager =
- (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
- }
- }
-
- @CallSuper
- @Override
- @Nullable
- public IBinder onBind(@NonNull Intent intent) {
- if (SERVICE_INTERFACE.equals(intent.getAction())) {
- synchronized (mLock) {
- return mStub;
- }
- }
- return null;
- }
-
- /**
- * Called by the system to notify that it is no longer used and is being removed. Do not call
- * this method directly.
- * <p>
- * Override this method if you need your own clean up. Derived classes MUST call through
- * to the super class's implementation of this method.
- */
- @CallSuper
- @Override
- public void onDestroy() {
- super.onDestroy();
- synchronized (mLock) {
- List<MediaSession2> sessions = getSessions();
- for (MediaSession2 session : sessions) {
- removeSession(session);
- }
- mSessions.clear();
- mNotifications.clear();
- }
- mStub.close();
- }
-
- /**
- * Called when a {@link MediaController2} is created with the this service's
- * {@link Session2Token}. Return the session for telling the controller which session to
- * connect. Return {@code null} to reject the connection from this controller.
- * <p>
- * Session returned here will be added to this service automatically. You don't need to call
- * {@link #addSession(MediaSession2)} for that.
- * <p>
- * This method is always called on the main thread.
- *
- * @param controllerInfo information of the controller which is trying to connect.
- * @return a {@link MediaSession2} instance for the controller to connect to, or {@code null}
- * to reject connection
- * @see MediaSession2.Builder
- * @see #getSessions()
- */
- @Nullable
- public abstract MediaSession2 onGetSession(@NonNull ControllerInfo controllerInfo);
-
- /**
- * Called when notification UI needs update. Override this method to show or cancel your own
- * notification UI.
- * <p>
- * This would be called on {@link MediaSession2}'s callback executor when playback state is
- * changed.
- * <p>
- * With the notification returned here, the service becomes foreground service when the playback
- * is started. Apps must request the permission
- * {@link android.Manifest.permission#FOREGROUND_SERVICE} in order to use this API. It becomes
- * background service after the playback is stopped.
- *
- * @param session a session that needs notification update.
- * @return a {@link MediaNotification}. Can be {@code null}.
- */
- @Nullable
- public abstract MediaNotification onUpdateNotification(@NonNull MediaSession2 session);
-
- /**
- * Adds a session to this service.
- * <p>
- * Added session will be removed automatically when it's closed, or removed when
- * {@link #removeSession} is called.
- *
- * @param session a session to be added.
- * @see #removeSession(MediaSession2)
- */
- public final void addSession(@NonNull MediaSession2 session) {
- if (session == null) {
- throw new IllegalArgumentException("session shouldn't be null");
- }
- if (session.isClosed()) {
- throw new IllegalArgumentException("session is already closed");
- }
- synchronized (mLock) {
- MediaSession2 previousSession = mSessions.get(session.getId());
- if (previousSession != null) {
- if (previousSession != session) {
- Log.w(TAG, "Session ID should be unique, ID=" + session.getId()
- + ", previous=" + previousSession + ", session=" + session);
- }
- return;
- }
- mSessions.put(session.getId(), session);
- session.setForegroundServiceEventCallback(mForegroundServiceEventCallback);
- }
- }
-
- /**
- * Removes a session from this service.
- *
- * @param session a session to be removed.
- * @see #addSession(MediaSession2)
- */
- public final void removeSession(@NonNull MediaSession2 session) {
- if (session == null) {
- throw new IllegalArgumentException("session shouldn't be null");
- }
- MediaNotification notification;
- synchronized (mLock) {
- if (mSessions.get(session.getId()) != session) {
- // Session isn't added or removed already.
- return;
- }
- mSessions.remove(session.getId());
- notification = mNotifications.remove(session);
- }
- session.setForegroundServiceEventCallback(null);
- if (notification != null) {
- mNotificationManager.cancel(notification.getNotificationId());
- }
- if (getSessions().isEmpty()) {
- stopForeground(false);
- }
- }
-
- /**
- * Gets the list of {@link MediaSession2}s that you've added to this service.
- *
- * @return sessions
- */
- public final @NonNull List<MediaSession2> getSessions() {
- List<MediaSession2> list = new ArrayList<>();
- synchronized (mLock) {
- list.addAll(mSessions.values());
- }
- return list;
- }
-
- /**
- * Returns the {@link MediaSessionManager}.
- */
- @NonNull
- MediaSessionManager getMediaSessionManager() {
- synchronized (mLock) {
- return mMediaSessionManager;
- }
- }
-
- /**
- * Called by registered {@link MediaSession2.ForegroundServiceEventCallback}
- *
- * @param session session with change
- * @param playbackActive {@code true} if playback is active.
- */
- void onPlaybackActiveChanged(MediaSession2 session, boolean playbackActive) {
- MediaNotification mediaNotification = onUpdateNotification(session);
- if (mediaNotification == null) {
- // The service implementation doesn't want to use the automatic start/stopForeground
- // feature.
- return;
- }
- synchronized (mLock) {
- mNotifications.put(session, mediaNotification);
- }
- int id = mediaNotification.getNotificationId();
- Notification notification = mediaNotification.getNotification();
- if (!playbackActive) {
- mNotificationManager.notify(id, notification);
- return;
- }
- // playbackActive == true
- startForegroundService(mStartSelfIntent);
- startForeground(id, notification);
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Returned by {@link #onUpdateNotification(MediaSession2)} for making session service
- * foreground service to keep playback running in the background. It's highly recommended to
- * show media style notification here.
- */
- public static class MediaNotification {
- private final int mNotificationId;
- private final Notification mNotification;
-
- /**
- * Default constructor
- *
- * @param notificationId notification id to be used for
- * {@link NotificationManager#notify(int, Notification)}.
- * @param notification a notification to make session service run in the foreground. Media
- * style notification is recommended here.
- */
- public MediaNotification(int notificationId, @NonNull Notification notification) {
- if (notification == null) {
- throw new IllegalArgumentException("notification shouldn't be null");
- }
- mNotificationId = notificationId;
- mNotification = notification;
- }
-
- /**
- * Gets the id of the notification.
- *
- * @return the notification id
- */
- public int getNotificationId() {
- return mNotificationId;
- }
-
- /**
- * Gets the notification.
- *
- * @return the notification
- */
- @NonNull
- public Notification getNotification() {
- return mNotification;
- }
- }
-
- private static final class MediaSession2ServiceStub extends IMediaSession2Service.Stub
- implements AutoCloseable {
- final WeakReference<MediaSession2Service> mService;
- final Handler mHandler;
-
- MediaSession2ServiceStub(MediaSession2Service service) {
- mService = new WeakReference<>(service);
- mHandler = new Handler(service.getMainLooper());
- }
-
- @Override
- public void connect(Controller2Link caller, int seq, Bundle connectionRequest) {
- if (mService.get() == null) {
- if (DEBUG) {
- Log.d(TAG, "Service is already destroyed");
- }
- return;
- }
- if (caller == null || connectionRequest == null) {
- if (DEBUG) {
- Log.d(TAG, "Ignoring calls with illegal arguments, caller=" + caller
- + ", connectionRequest=" + connectionRequest);
- }
- return;
- }
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- mHandler.post(() -> {
- boolean shouldNotifyDisconnected = true;
- try {
- final MediaSession2Service service = mService.get();
- if (service == null) {
- if (DEBUG) {
- Log.d(TAG, "Service isn't available");
- }
- return;
- }
-
- String callingPkg = connectionRequest.getString(KEY_PACKAGE_NAME);
- // The Binder.getCallingPid() can be 0 for an oneway call from the
- // remote process. If it's the case, use PID from the connectionRequest.
- RemoteUserInfo remoteUserInfo = new RemoteUserInfo(
- callingPkg,
- pid == 0 ? connectionRequest.getInt(KEY_PID) : pid,
- uid);
-
- Bundle connectionHints = connectionRequest.getBundle(KEY_CONNECTION_HINTS);
- if (connectionHints == null) {
- Log.w(TAG, "connectionHints shouldn't be null.");
- connectionHints = Bundle.EMPTY;
- } else if (MediaSession2.hasCustomParcelable(connectionHints)) {
- Log.w(TAG, "connectionHints contain custom parcelable. Ignoring.");
- connectionHints = Bundle.EMPTY;
- }
-
- final ControllerInfo controllerInfo = new ControllerInfo(
- remoteUserInfo,
- service.getMediaSessionManager()
- .isTrustedForMediaControl(remoteUserInfo),
- caller,
- connectionHints);
-
- if (DEBUG) {
- Log.d(TAG, "Handling incoming connection request from the"
- + " controller=" + controllerInfo);
- }
-
- final MediaSession2 session;
- session = service.onGetSession(controllerInfo);
-
- if (session == null) {
- if (DEBUG) {
- Log.d(TAG, "Rejecting incoming connection request from the"
- + " controller=" + controllerInfo);
- }
- // Note: Trusted controllers also can be rejected according to the
- // service implementation.
- return;
- }
- service.addSession(session);
- shouldNotifyDisconnected = false;
- session.onConnect(caller, pid, uid, seq, connectionRequest);
- } catch (Exception e) {
- // Don't propagate exception in service to the controller.
- Log.w(TAG, "Failed to add a session to session service", e);
- } finally {
- // Trick to call onDisconnected() in one place.
- if (shouldNotifyDisconnected) {
- if (DEBUG) {
- Log.d(TAG, "Notifying the controller of its disconnection");
- }
- try {
- caller.notifyDisconnected(0);
- } catch (RuntimeException e) {
- // Controller may be died prematurely.
- // Not an issue because we'll ignore it anyway.
- }
- }
- }
- });
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void close() {
- mHandler.removeCallbacksAndMessages(null);
- mService.clear();
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/MediaTranscodingManager.java b/apex/media/framework/java/android/media/MediaTranscodingManager.java
deleted file mode 100644
index 1a84929..0000000
--- a/apex/media/framework/java/android/media/MediaTranscodingManager.java
+++ /dev/null
@@ -1,1752 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.annotation.CallbackExecutor;
-import android.annotation.IntDef;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.net.Uri;
-import android.os.Build;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.ServiceSpecificException;
-import android.system.Os;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.modules.annotation.MinSdk;
-import com.android.modules.utils.build.SdkLevel;
-
-import java.io.FileNotFoundException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-/**
- Android 12 introduces Compatible media transcoding feature. See
- <a href="https://developer.android.com/about/versions/12/features#compatible_media_transcoding">
- Compatible media transcoding</a>. MediaTranscodingManager provides an interface to the system's media
- transcoding service and can be used to transcode media files, e.g. transcoding a video from HEVC to
- AVC.
-
- <h3>Transcoding Types</h3>
- <h4>Video Transcoding</h4>
- When transcoding a video file, the video track will be transcoded based on the desired track format
- and the audio track will be pass through without any modification.
- <p class=note>
- Note that currently only support transcoding video file in mp4 format and with single video track.
-
- <h3>Transcoding Request</h3>
- <p>
- To transcode a media file, first create a {@link TranscodingRequest} through its builder class
- {@link VideoTranscodingRequest.Builder}. Transcode requests are then enqueue to the manager through
- {@link MediaTranscodingManager#enqueueRequest(
- TranscodingRequest, Executor, OnTranscodingFinishedListener)}
- TranscodeRequest are processed based on client process's priority and request priority. When a
- transcode operation is completed the caller is notified via its
- {@link OnTranscodingFinishedListener}.
- In the meantime the caller may use the returned TranscodingSession object to cancel or check the
- status of a specific transcode operation.
- <p>
- Here is an example where <code>Builder</code> is used to specify all parameters
-
- <pre class=prettyprint>
- VideoTranscodingRequest request =
- new VideoTranscodingRequest.Builder(srcUri, dstUri, videoFormat).build();
- }</pre>
- @hide
- */
-@MinSdk(Build.VERSION_CODES.S)
-@SystemApi
-public final class MediaTranscodingManager {
- private static final String TAG = "MediaTranscodingManager";
-
- /** Maximum number of retry to connect to the service. */
- private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
-
- /** Interval between trying to reconnect to the service. */
- private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40;
-
- /** Default bpp(bits-per-pixel) to use for calculating default bitrate. */
- private static final float BPP = 0.25f;
-
- /**
- * Listener that gets notified when a transcoding operation has finished.
- * This listener gets notified regardless of how the operation finished. It is up to the
- * listener implementation to check the result and take appropriate action.
- */
- @FunctionalInterface
- public interface OnTranscodingFinishedListener {
- /**
- * Called when the transcoding operation has finished. The receiver may use the
- * TranscodingSession to check the result, i.e. whether the operation succeeded, was
- * canceled or if an error occurred.
- *
- * @param session The TranscodingSession instance for the finished transcoding operation.
- */
- void onTranscodingFinished(@NonNull TranscodingSession session);
- }
-
- private final Context mContext;
- private ContentResolver mContentResolver;
- private final String mPackageName;
- private final int mPid;
- private final int mUid;
- private final boolean mIsLowRamDevice;
- private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
- private final HashMap<Integer, TranscodingSession> mPendingTranscodingSessions = new HashMap();
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- @NonNull private ITranscodingClient mTranscodingClient = null;
- private static MediaTranscodingManager sMediaTranscodingManager;
-
- private void handleTranscodingFinished(int sessionId, TranscodingResultParcel result) {
- synchronized (mPendingTranscodingSessions) {
- // Gets the session associated with the sessionId and removes it from
- // mPendingTranscodingSessions.
- final TranscodingSession session = mPendingTranscodingSessions.remove(sessionId);
-
- if (session == null) {
- // This should not happen in reality.
- Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
- return;
- }
-
- // Updates the session status and result.
- session.updateStatusAndResult(TranscodingSession.STATUS_FINISHED,
- TranscodingSession.RESULT_SUCCESS,
- TranscodingSession.ERROR_NONE);
-
- // Notifies client the session is done.
- if (session.mListener != null && session.mListenerExecutor != null) {
- session.mListenerExecutor.execute(
- () -> session.mListener.onTranscodingFinished(session));
- }
- }
- }
-
- private void handleTranscodingFailed(int sessionId, int errorCode) {
- synchronized (mPendingTranscodingSessions) {
- // Gets the session associated with the sessionId and removes it from
- // mPendingTranscodingSessions.
- final TranscodingSession session = mPendingTranscodingSessions.remove(sessionId);
-
- if (session == null) {
- // This should not happen in reality.
- Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
- return;
- }
-
- // Updates the session status and result.
- session.updateStatusAndResult(TranscodingSession.STATUS_FINISHED,
- TranscodingSession.RESULT_ERROR, errorCode);
-
- // Notifies client the session failed.
- if (session.mListener != null && session.mListenerExecutor != null) {
- session.mListenerExecutor.execute(
- () -> session.mListener.onTranscodingFinished(session));
- }
- }
- }
-
- private void handleTranscodingProgressUpdate(int sessionId, int newProgress) {
- synchronized (mPendingTranscodingSessions) {
- // Gets the session associated with the sessionId.
- final TranscodingSession session = mPendingTranscodingSessions.get(sessionId);
-
- if (session == null) {
- // This should not happen in reality.
- Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
- return;
- }
-
- // Updates the session progress.
- session.updateProgress(newProgress);
-
- // Notifies client the progress update.
- if (session.mProgressUpdateExecutor != null
- && session.mProgressUpdateListener != null) {
- session.mProgressUpdateExecutor.execute(
- () -> session.mProgressUpdateListener.onProgressUpdate(session,
- newProgress));
- }
- }
- }
-
- private IMediaTranscodingService getService(boolean retry) {
- // Do not try to get the service on pre-S. The service is lazy-start and getting the
- // service could block.
- if (!SdkLevel.isAtLeastS()) {
- return null;
- }
- // Do not try to get the service on AndroidGo (low-ram) devices.
- if (mIsLowRamDevice) {
- return null;
- }
- int retryCount = !retry ? 1 : CONNECT_SERVICE_RETRY_COUNT;
- Log.i(TAG, "get service with retry " + retryCount);
- for (int count = 1; count <= retryCount; count++) {
- Log.d(TAG, "Trying to connect to service. Try count: " + count);
- IMediaTranscodingService service = IMediaTranscodingService.Stub.asInterface(
- MediaFrameworkInitializer
- .getMediaServiceManager()
- .getMediaTranscodingServiceRegisterer()
- .get());
- if (service != null) {
- return service;
- }
- try {
- // Sleep a bit before retry.
- Thread.sleep(INTERVAL_CONNECT_SERVICE_RETRY_MS);
- } catch (InterruptedException ie) {
- /* ignore */
- }
- }
- Log.w(TAG, "Failed to get service");
- return null;
- }
-
- /*
- * Handle client binder died event.
- * Upon receiving a binder died event of the client, we will do the following:
- * 1) For the session that is running, notify the client that the session is failed with
- * error code, so client could choose to retry the session or not.
- * TODO(hkuang): Add a new error code to signal service died error.
- * 2) For the sessions that is still pending or paused, we will resubmit the session
- * once we successfully reconnect to the service and register a new client.
- * 3) When trying to connect to the service and register a new client. The service may need time
- * to reboot or never boot up again. So we will retry for a number of times. If we still
- * could not connect, we will notify client session failure for the pending and paused
- * sessions.
- */
- private void onClientDied() {
- synchronized (mLock) {
- mTranscodingClient = null;
- }
-
- // Delegates the session notification and retry to the executor as it may take some time.
- mExecutor.execute(() -> {
- // List to track the sessions that we want to retry.
- List<TranscodingSession> retrySessions = new ArrayList<TranscodingSession>();
-
- // First notify the client of session failure for all the running sessions.
- synchronized (mPendingTranscodingSessions) {
- for (Map.Entry<Integer, TranscodingSession> entry :
- mPendingTranscodingSessions.entrySet()) {
- TranscodingSession session = entry.getValue();
-
- if (session.getStatus() == TranscodingSession.STATUS_RUNNING) {
- session.updateStatusAndResult(TranscodingSession.STATUS_FINISHED,
- TranscodingSession.RESULT_ERROR,
- TranscodingSession.ERROR_SERVICE_DIED);
-
- // Remove the session from pending sessions.
- mPendingTranscodingSessions.remove(entry.getKey());
-
- if (session.mListener != null && session.mListenerExecutor != null) {
- Log.i(TAG, "Notify client session failed");
- session.mListenerExecutor.execute(
- () -> session.mListener.onTranscodingFinished(session));
- }
- } else if (session.getStatus() == TranscodingSession.STATUS_PENDING
- || session.getStatus() == TranscodingSession.STATUS_PAUSED) {
- // Add the session to retrySessions to handle them later.
- retrySessions.add(session);
- }
- }
- }
-
- // Try to register with the service once it boots up.
- IMediaTranscodingService service = getService(true /*retry*/);
- boolean haveTranscodingClient = false;
- if (service != null) {
- synchronized (mLock) {
- mTranscodingClient = registerClient(service);
- if (mTranscodingClient != null) {
- haveTranscodingClient = true;
- }
- }
- }
-
- for (TranscodingSession session : retrySessions) {
- // Notify the session failure if we fails to connect to the service or fail
- // to retry the session.
- if (!haveTranscodingClient) {
- // TODO(hkuang): Return correct error code to the client.
- handleTranscodingFailed(session.getSessionId(), 0 /*unused */);
- }
-
- try {
- // Do not set hasRetried for retry initiated by MediaTranscodingManager.
- session.retryInternal(false /*setHasRetried*/);
- } catch (Exception re) {
- // TODO(hkuang): Return correct error code to the client.
- handleTranscodingFailed(session.getSessionId(), 0 /*unused */);
- }
- }
- });
- }
-
- private void updateStatus(int sessionId, int status) {
- synchronized (mPendingTranscodingSessions) {
- final TranscodingSession session = mPendingTranscodingSessions.get(sessionId);
-
- if (session == null) {
- // This should not happen in reality.
- Log.e(TAG, "Session " + sessionId + " is not in Pendingsessions");
- return;
- }
-
- // Updates the session status.
- session.updateStatus(status);
- }
- }
-
- // Just forwards all the events to the event handler.
- private ITranscodingClientCallback mTranscodingClientCallback =
- new ITranscodingClientCallback.Stub() {
- // TODO(hkuang): Add more unit test to test difference file open mode.
- @Override
- public ParcelFileDescriptor openFileDescriptor(String fileUri, String mode)
- throws RemoteException {
- if (!mode.equals("r") && !mode.equals("w") && !mode.equals("rw")) {
- Log.e(TAG, "Unsupport mode: " + mode);
- return null;
- }
-
- Uri uri = Uri.parse(fileUri);
- try {
- AssetFileDescriptor afd = mContentResolver.openAssetFileDescriptor(uri,
- mode);
- if (afd != null) {
- return afd.getParcelFileDescriptor();
- }
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Cannot find content uri: " + uri, e);
- } catch (SecurityException e) {
- Log.w(TAG, "Cannot open content uri: " + uri, e);
- } catch (Exception e) {
- Log.w(TAG, "Unknown content uri: " + uri, e);
- }
- return null;
- }
-
- @Override
- public void onTranscodingStarted(int sessionId) throws RemoteException {
- updateStatus(sessionId, TranscodingSession.STATUS_RUNNING);
- }
-
- @Override
- public void onTranscodingPaused(int sessionId) throws RemoteException {
- updateStatus(sessionId, TranscodingSession.STATUS_PAUSED);
- }
-
- @Override
- public void onTranscodingResumed(int sessionId) throws RemoteException {
- updateStatus(sessionId, TranscodingSession.STATUS_RUNNING);
- }
-
- @Override
- public void onTranscodingFinished(int sessionId, TranscodingResultParcel result)
- throws RemoteException {
- handleTranscodingFinished(sessionId, result);
- }
-
- @Override
- public void onTranscodingFailed(int sessionId, int errorCode)
- throws RemoteException {
- handleTranscodingFailed(sessionId, errorCode);
- }
-
- @Override
- public void onAwaitNumberOfSessionsChanged(int sessionId, int oldAwaitNumber,
- int newAwaitNumber) throws RemoteException {
- //TODO(hkuang): Implement this.
- }
-
- @Override
- public void onProgressUpdate(int sessionId, int newProgress)
- throws RemoteException {
- handleTranscodingProgressUpdate(sessionId, newProgress);
- }
- };
-
- private ITranscodingClient registerClient(IMediaTranscodingService service) {
- synchronized (mLock) {
- try {
- // Registers the client with MediaTranscoding service.
- mTranscodingClient = service.registerClient(
- mTranscodingClientCallback,
- mPackageName,
- mPackageName);
-
- if (mTranscodingClient != null) {
- mTranscodingClient.asBinder().linkToDeath(() -> onClientDied(), /* flags */ 0);
- }
- } catch (Exception ex) {
- Log.e(TAG, "Failed to register new client due to exception " + ex);
- mTranscodingClient = null;
- }
- }
- return mTranscodingClient;
- }
-
- /**
- * @hide
- */
- public MediaTranscodingManager(@NonNull Context context) {
- mContext = context;
- mContentResolver = mContext.getContentResolver();
- mPackageName = mContext.getPackageName();
- mUid = Os.getuid();
- mPid = Os.getpid();
- mIsLowRamDevice = mContext.getSystemService(ActivityManager.class).isLowRamDevice();
- }
-
- /**
- * Abstract base class for all the TranscodingRequest.
- * <p> TranscodingRequest encapsulates the desired configuration for the transcoding.
- */
- public abstract static class TranscodingRequest {
- /**
- *
- * Default transcoding type.
- * @hide
- */
- public static final int TRANSCODING_TYPE_UNKNOWN = 0;
-
- /**
- * TRANSCODING_TYPE_VIDEO indicates that client wants to perform transcoding on a video.
- * <p>Note that currently only support transcoding video file in mp4 format.
- * @hide
- */
- public static final int TRANSCODING_TYPE_VIDEO = 1;
-
- /**
- * TRANSCODING_TYPE_IMAGE indicates that client wants to perform transcoding on an image.
- * @hide
- */
- public static final int TRANSCODING_TYPE_IMAGE = 2;
-
- /** @hide */
- @IntDef(prefix = {"TRANSCODING_TYPE_"}, value = {
- TRANSCODING_TYPE_UNKNOWN,
- TRANSCODING_TYPE_VIDEO,
- TRANSCODING_TYPE_IMAGE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TranscodingType {}
-
- /**
- * Default value.
- *
- * @hide
- */
- public static final int PRIORITY_UNKNOWN = 0;
- /**
- * PRIORITY_REALTIME indicates that the transcoding request is time-critical and that the
- * client wants the transcoding result as soon as possible.
- * <p> Set PRIORITY_REALTIME only if the transcoding is time-critical as it will involve
- * performance penalty due to resource reallocation to prioritize the sessions with higher
- * priority.
- *
- * @hide
- */
- public static final int PRIORITY_REALTIME = 1;
-
- /**
- * PRIORITY_OFFLINE indicates the transcoding is not time-critical and the client does not
- * need the transcoding result as soon as possible.
- * <p>Sessions with PRIORITY_OFFLINE will be scheduled behind PRIORITY_REALTIME. Always set
- * to
- * PRIORITY_OFFLINE if client does not need the result as soon as possible and could accept
- * delay of the transcoding result.
- *
- * @hide
- *
- */
- public static final int PRIORITY_OFFLINE = 2;
-
- /** @hide */
- @IntDef(prefix = {"PRIORITY_"}, value = {
- PRIORITY_UNKNOWN,
- PRIORITY_REALTIME,
- PRIORITY_OFFLINE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TranscodingPriority {}
-
- /** Uri of the source media file. */
- private @NonNull Uri mSourceUri;
-
- /** Uri of the destination media file. */
- private @NonNull Uri mDestinationUri;
-
- /** FileDescriptor of the source media file. */
- private @Nullable ParcelFileDescriptor mSourceFileDescriptor;
-
- /** FileDescriptor of the destination media file. */
- private @Nullable ParcelFileDescriptor mDestinationFileDescriptor;
-
- /**
- * The UID of the client that the TranscodingRequest is for. Only privileged caller could
- * set this Uid as only they could do the transcoding on behalf of the client.
- * -1 means not available.
- */
- private int mClientUid = -1;
-
- /**
- * The Pid of the client that the TranscodingRequest is for. Only privileged caller could
- * set this Uid as only they could do the transcoding on behalf of the client.
- * -1 means not available.
- */
- private int mClientPid = -1;
-
- /** Type of the transcoding. */
- private @TranscodingType int mType = TRANSCODING_TYPE_UNKNOWN;
-
- /** Priority of the transcoding. */
- private @TranscodingPriority int mPriority = PRIORITY_UNKNOWN;
-
- /**
- * Desired image format for the destination file.
- * <p> If this is null, source file's image track will be passed through and copied to the
- * destination file.
- * @hide
- */
- private @Nullable MediaFormat mImageFormat = null;
-
- @VisibleForTesting
- private TranscodingTestConfig mTestConfig = null;
-
- /**
- * Prevent public constructor access.
- */
- /* package private */ TranscodingRequest() {
- }
-
- private TranscodingRequest(Builder b) {
- mSourceUri = b.mSourceUri;
- mSourceFileDescriptor = b.mSourceFileDescriptor;
- mDestinationUri = b.mDestinationUri;
- mDestinationFileDescriptor = b.mDestinationFileDescriptor;
- mClientUid = b.mClientUid;
- mClientPid = b.mClientPid;
- mPriority = b.mPriority;
- mType = b.mType;
- mTestConfig = b.mTestConfig;
- }
-
- /**
- * Return the type of the transcoding.
- * @hide
- */
- @TranscodingType
- public int getType() {
- return mType;
- }
-
- /** Return source uri of the transcoding. */
- @NonNull
- public Uri getSourceUri() {
- return mSourceUri;
- }
-
- /**
- * Return source file descriptor of the transcoding.
- * This will be null if client has not provided it.
- */
- @Nullable
- public ParcelFileDescriptor getSourceFileDescriptor() {
- return mSourceFileDescriptor;
- }
-
- /** Return the UID of the client that this request is for. -1 means not available. */
- public int getClientUid() {
- return mClientUid;
- }
-
- /** Return the PID of the client that this request is for. -1 means not available. */
- public int getClientPid() {
- return mClientPid;
- }
-
- /** Return destination uri of the transcoding. */
- @NonNull
- public Uri getDestinationUri() {
- return mDestinationUri;
- }
-
- /**
- * Return destination file descriptor of the transcoding.
- * This will be null if client has not provided it.
- */
- @Nullable
- public ParcelFileDescriptor getDestinationFileDescriptor() {
- return mDestinationFileDescriptor;
- }
-
- /**
- * Return priority of the transcoding.
- * @hide
- */
- @TranscodingPriority
- public int getPriority() {
- return mPriority;
- }
-
- /**
- * Return TestConfig of the transcoding.
- * @hide
- */
- @Nullable
- public TranscodingTestConfig getTestConfig() {
- return mTestConfig;
- }
-
- abstract void writeFormatToParcel(TranscodingRequestParcel parcel);
-
- /* Writes the TranscodingRequest to a parcel. */
- private TranscodingRequestParcel writeToParcel(@NonNull Context context) {
- TranscodingRequestParcel parcel = new TranscodingRequestParcel();
- switch (mPriority) {
- case PRIORITY_OFFLINE:
- parcel.priority = TranscodingSessionPriority.kUnspecified;
- break;
- case PRIORITY_REALTIME:
- case PRIORITY_UNKNOWN:
- default:
- parcel.priority = TranscodingSessionPriority.kNormal;
- break;
- }
- parcel.transcodingType = mType;
- parcel.sourceFilePath = mSourceUri.toString();
- parcel.sourceFd = mSourceFileDescriptor;
- parcel.destinationFilePath = mDestinationUri.toString();
- parcel.destinationFd = mDestinationFileDescriptor;
- parcel.clientUid = mClientUid;
- parcel.clientPid = mClientPid;
- if (mClientUid < 0) {
- parcel.clientPackageName = context.getPackageName();
- } else {
- String packageName = context.getPackageManager().getNameForUid(mClientUid);
- // PackageName is optional as some uid does not have package name. Set to
- // "Unavailable" string in this case.
- if (packageName == null) {
- Log.w(TAG, "Failed to find package for uid: " + mClientUid);
- packageName = "Unavailable";
- }
- parcel.clientPackageName = packageName;
- }
- writeFormatToParcel(parcel);
- if (mTestConfig != null) {
- parcel.isForTesting = true;
- parcel.testConfig = mTestConfig;
- }
- return parcel;
- }
-
- /**
- * Builder to build a {@link TranscodingRequest} object.
- *
- * @param <T> The subclass to be built.
- */
- abstract static class Builder<T extends Builder<T>> {
- private @NonNull Uri mSourceUri;
- private @NonNull Uri mDestinationUri;
- private @Nullable ParcelFileDescriptor mSourceFileDescriptor = null;
- private @Nullable ParcelFileDescriptor mDestinationFileDescriptor = null;
- private int mClientUid = -1;
- private int mClientPid = -1;
- private @TranscodingType int mType = TRANSCODING_TYPE_UNKNOWN;
- private @TranscodingPriority int mPriority = PRIORITY_UNKNOWN;
- private TranscodingTestConfig mTestConfig;
-
- abstract T self();
-
- /**
- * Creates a builder for building {@link TranscodingRequest}s.
- *
- * Client must set the source Uri. If client also provides the source fileDescriptor
- * through is provided by {@link #setSourceFileDescriptor(ParcelFileDescriptor)},
- * TranscodingSession will use the fd instead of calling back to the client to open the
- * sourceUri.
- *
- *
- * @param type The transcoding type.
- * @param sourceUri Content uri for the source media file.
- * @param destinationUri Content uri for the destination media file.
- *
- */
- private Builder(@TranscodingType int type, @NonNull Uri sourceUri,
- @NonNull Uri destinationUri) {
- mType = type;
-
- if (sourceUri == null || Uri.EMPTY.equals(sourceUri)) {
- throw new IllegalArgumentException(
- "You must specify a non-empty source Uri.");
- }
- mSourceUri = sourceUri;
-
- if (destinationUri == null || Uri.EMPTY.equals(destinationUri)) {
- throw new IllegalArgumentException(
- "You must specify a non-empty destination Uri.");
- }
- mDestinationUri = destinationUri;
- }
-
- /**
- * Specifies the fileDescriptor opened from the source media file.
- *
- * This call is optional. If the source fileDescriptor is provided, TranscodingSession
- * will use it directly instead of opening the uri from {@link #Builder(int, Uri, Uri)}.
- * It is client's responsibility to make sure the fileDescriptor is opened from the
- * source uri.
- * @param fileDescriptor a {@link ParcelFileDescriptor} opened from source media file.
- * @return The same builder instance.
- * @throws IllegalArgumentException if fileDescriptor is invalid.
- */
- @NonNull
- public T setSourceFileDescriptor(@NonNull ParcelFileDescriptor fileDescriptor) {
- if (fileDescriptor == null || fileDescriptor.getFd() < 0) {
- throw new IllegalArgumentException(
- "Invalid source descriptor.");
- }
- mSourceFileDescriptor = fileDescriptor;
- return self();
- }
-
- /**
- * Specifies the fileDescriptor opened from the destination media file.
- *
- * This call is optional. If the destination fileDescriptor is provided,
- * TranscodingSession will use it directly instead of opening the source uri from
- * {@link #Builder(int, Uri, Uri)} upon transcoding starts. It is client's
- * responsibility to make sure the fileDescriptor is opened from the destination uri.
- * @param fileDescriptor a {@link ParcelFileDescriptor} opened from destination media
- * file.
- * @return The same builder instance.
- * @throws IllegalArgumentException if fileDescriptor is invalid.
- */
- @NonNull
- public T setDestinationFileDescriptor(
- @NonNull ParcelFileDescriptor fileDescriptor) {
- if (fileDescriptor == null || fileDescriptor.getFd() < 0) {
- throw new IllegalArgumentException(
- "Invalid destination descriptor.");
- }
- mDestinationFileDescriptor = fileDescriptor;
- return self();
- }
-
- /**
- * Specify the UID of the client that this request is for.
- * <p>
- * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could forward the
- * pid. Note that the permission check happens on the service side upon starting the
- * transcoding. If the client does not have the permission, the transcoding will fail.
- *
- * @param uid client Uid.
- * @return The same builder instance.
- * @throws IllegalArgumentException if uid is invalid.
- */
- @NonNull
- public T setClientUid(int uid) {
- if (uid < 0) {
- throw new IllegalArgumentException("Invalid Uid");
- }
- mClientUid = uid;
- return self();
- }
-
- /**
- * Specify the pid of the client that this request is for.
- * <p>
- * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could forward the
- * pid. Note that the permission check happens on the service side upon starting the
- * transcoding. If the client does not have the permission, the transcoding will fail.
- *
- * @param pid client Pid.
- * @return The same builder instance.
- * @throws IllegalArgumentException if pid is invalid.
- */
- @NonNull
- public T setClientPid(int pid) {
- if (pid < 0) {
- throw new IllegalArgumentException("Invalid pid");
- }
- mClientPid = pid;
- return self();
- }
-
- /**
- * Specifies the priority of the transcoding.
- *
- * @param priority Must be one of the {@code PRIORITY_*}
- * @return The same builder instance.
- * @throws IllegalArgumentException if flags is invalid.
- * @hide
- */
- @NonNull
- public T setPriority(@TranscodingPriority int priority) {
- if (priority != PRIORITY_OFFLINE && priority != PRIORITY_REALTIME) {
- throw new IllegalArgumentException("Invalid priority: " + priority);
- }
- mPriority = priority;
- return self();
- }
-
- /**
- * Sets the delay in processing this request.
- * @param config test config.
- * @return The same builder instance.
- * @hide
- */
- @VisibleForTesting
- @NonNull
- public T setTestConfig(@NonNull TranscodingTestConfig config) {
- mTestConfig = config;
- return self();
- }
- }
-
- /**
- * Abstract base class for all the format resolvers.
- */
- abstract static class MediaFormatResolver {
- private @NonNull ApplicationMediaCapabilities mClientCaps;
-
- /**
- * Prevents public constructor access.
- */
- /* package private */ MediaFormatResolver() {
- }
-
- /**
- * Constructs MediaFormatResolver object.
- *
- * @param clientCaps An ApplicationMediaCapabilities object containing the client's
- * capabilities.
- */
- MediaFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps) {
- if (clientCaps == null) {
- throw new IllegalArgumentException("Client capabilities must not be null");
- }
- mClientCaps = clientCaps;
- }
-
- /**
- * Returns the client capabilities.
- */
- @NonNull
- /* package */ ApplicationMediaCapabilities getClientCapabilities() {
- return mClientCaps;
- }
-
- abstract boolean shouldTranscode();
- }
-
- /**
- * VideoFormatResolver for deciding if video transcoding is needed, and if so, the track
- * formats to use.
- */
- public static class VideoFormatResolver extends MediaFormatResolver {
- private static final int BIT_RATE = 20000000; // 20Mbps
-
- private MediaFormat mSrcVideoFormatHint;
- private MediaFormat mSrcAudioFormatHint;
-
- /**
- * Constructs a new VideoFormatResolver object.
- *
- * @param clientCaps An ApplicationMediaCapabilities object containing the client's
- * capabilities.
- * @param srcVideoFormatHint A MediaFormat object containing information about the
- * source's video track format that could affect the
- * transcoding decision. Such information could include video
- * codec types, color spaces, whether special format info (eg.
- * slow-motion markers) are present, etc.. If a particular
- * information is not present, it will not be used to make the
- * decision.
- */
- public VideoFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps,
- @NonNull MediaFormat srcVideoFormatHint) {
- super(clientCaps);
- mSrcVideoFormatHint = srcVideoFormatHint;
- }
-
- /**
- * Constructs a new VideoFormatResolver object.
- *
- * @param clientCaps An ApplicationMediaCapabilities object containing the client's
- * capabilities.
- * @param srcVideoFormatHint A MediaFormat object containing information about the
- * source's video track format that could affect the
- * transcoding decision. Such information could include video
- * codec types, color spaces, whether special format info (eg.
- * slow-motion markers) are present, etc.. If a particular
- * information is not present, it will not be used to make the
- * decision.
- * @param srcAudioFormatHint A MediaFormat object containing information about the
- * source's audio track format that could affect the
- * transcoding decision.
- * @hide
- */
- VideoFormatResolver(@NonNull ApplicationMediaCapabilities clientCaps,
- @NonNull MediaFormat srcVideoFormatHint,
- @NonNull MediaFormat srcAudioFormatHint) {
- super(clientCaps);
- mSrcVideoFormatHint = srcVideoFormatHint;
- mSrcAudioFormatHint = srcAudioFormatHint;
- }
-
- /**
- * Returns whether the source content should be transcoded.
- *
- * @return true if the source should be transcoded.
- */
- public boolean shouldTranscode() {
- boolean supportHevc = getClientCapabilities().isVideoMimeTypeSupported(
- MediaFormat.MIMETYPE_VIDEO_HEVC);
- if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals(
- mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) {
- return true;
- }
- // TODO: add more checks as needed below.
- return false;
- }
-
- /**
- * Retrieves the video track format to be used on
- * {@link VideoTranscodingRequest.Builder#setVideoTrackFormat(MediaFormat)} for this
- * configuration.
- *
- * @return the video track format to be used if transcoding should be performed,
- * and null otherwise.
- * @throws IllegalArgumentException if the hinted source video format contains invalid
- * parameters.
- */
- @Nullable
- public MediaFormat resolveVideoFormat() {
- if (!shouldTranscode()) {
- return null;
- }
-
- MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint);
- videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);
-
- int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH, -1);
- int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT, -1);
- if (width <= 0 || height <= 0) {
- throw new IllegalArgumentException(
- "Source Width and height must be larger than 0");
- }
-
- float frameRate =
- mSrcVideoFormatHint.getNumber(MediaFormat.KEY_FRAME_RATE, 30.0)
- .floatValue();
- if (frameRate <= 0) {
- throw new IllegalArgumentException(
- "frameRate must be larger than 0");
- }
-
- int bitrate = getAVCBitrate(width, height, frameRate);
- videoTrackFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
- return videoTrackFormat;
- }
-
- /**
- * Generate a default bitrate with the fixed bpp(bits-per-pixel) 0.25.
- * This maps to:
- * 1080P@30fps -> 16Mbps
- * 1080P@60fps-> 32Mbps
- * 4K@30fps -> 62Mbps
- */
- private static int getDefaultBitrate(int width, int height, float frameRate) {
- return (int) (width * height * frameRate * BPP);
- }
-
- /**
- * Query the bitrate from CamcorderProfile. If there are two profiles that match the
- * width/height/framerate, we will use the higher one to get better quality.
- * Return default bitrate if could not find any match profile.
- */
- private static int getAVCBitrate(int width, int height, float frameRate) {
- int bitrate = -1;
- int[] cameraIds = {0, 1};
-
- // Profiles ordered in decreasing order of preference.
- int[] preferQualities = {
- CamcorderProfile.QUALITY_2160P,
- CamcorderProfile.QUALITY_1080P,
- CamcorderProfile.QUALITY_720P,
- CamcorderProfile.QUALITY_480P,
- CamcorderProfile.QUALITY_LOW,
- };
-
- for (int cameraId : cameraIds) {
- for (int quality : preferQualities) {
- // Check if camera id has profile for the quality level.
- if (!CamcorderProfile.hasProfile(cameraId, quality)) {
- continue;
- }
- CamcorderProfile profile = CamcorderProfile.get(cameraId, quality);
- // Check the width/height/framerate/codec, also consider portrait case.
- if (((width == profile.videoFrameWidth
- && height == profile.videoFrameHeight)
- || (height == profile.videoFrameWidth
- && width == profile.videoFrameHeight))
- && (int) frameRate == profile.videoFrameRate
- && profile.videoCodec == MediaRecorder.VideoEncoder.H264) {
- if (bitrate < profile.videoBitRate) {
- bitrate = profile.videoBitRate;
- }
- break;
- }
- }
- }
-
- if (bitrate == -1) {
- Log.w(TAG, "Failed to find CamcorderProfile for w: " + width + "h: " + height
- + " fps: "
- + frameRate);
- bitrate = getDefaultBitrate(width, height, frameRate);
- }
- Log.d(TAG, "Using bitrate " + bitrate + " for " + width + " " + height + " "
- + frameRate);
- return bitrate;
- }
-
- /**
- * Retrieves the audio track format to be used for transcoding.
- *
- * @return the audio track format to be used if transcoding should be performed, and
- * null otherwise.
- * @hide
- */
- @Nullable
- public MediaFormat resolveAudioFormat() {
- if (!shouldTranscode()) {
- return null;
- }
- // Audio transcoding is not supported yet, always return null.
- return null;
- }
- }
- }
-
- /**
- * VideoTranscodingRequest encapsulates the configuration for transcoding a video.
- */
- public static final class VideoTranscodingRequest extends TranscodingRequest {
- /**
- * Desired output video format of the destination file.
- * <p> If this is null, source file's video track will be passed through and copied to the
- * destination file.
- */
- private @Nullable MediaFormat mVideoTrackFormat = null;
-
- /**
- * Desired output audio format of the destination file.
- * <p> If this is null, source file's audio track will be passed through and copied to the
- * destination file.
- */
- private @Nullable MediaFormat mAudioTrackFormat = null;
-
- private VideoTranscodingRequest(VideoTranscodingRequest.Builder builder) {
- super(builder);
- mVideoTrackFormat = builder.mVideoTrackFormat;
- mAudioTrackFormat = builder.mAudioTrackFormat;
- }
-
- /**
- * Return the video track format of the transcoding.
- * This will be null if client has not specified the video track format.
- */
- @NonNull
- public MediaFormat getVideoTrackFormat() {
- return mVideoTrackFormat;
- }
-
- @Override
- void writeFormatToParcel(TranscodingRequestParcel parcel) {
- parcel.requestedVideoTrackFormat = convertToVideoTrackFormat(mVideoTrackFormat);
- }
-
- /* Converts the MediaFormat to TranscodingVideoTrackFormat. */
- private static TranscodingVideoTrackFormat convertToVideoTrackFormat(MediaFormat format) {
- if (format == null) {
- throw new IllegalArgumentException("Invalid MediaFormat");
- }
-
- TranscodingVideoTrackFormat trackFormat = new TranscodingVideoTrackFormat();
-
- if (format.containsKey(MediaFormat.KEY_MIME)) {
- String mime = format.getString(MediaFormat.KEY_MIME);
- if (MediaFormat.MIMETYPE_VIDEO_AVC.equals(mime)) {
- trackFormat.codecType = TranscodingVideoCodecType.kAvc;
- } else if (MediaFormat.MIMETYPE_VIDEO_HEVC.equals(mime)) {
- trackFormat.codecType = TranscodingVideoCodecType.kHevc;
- } else {
- throw new UnsupportedOperationException("Only support transcode to avc/hevc");
- }
- }
-
- if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
- int bitrateBps = format.getInteger(MediaFormat.KEY_BIT_RATE);
- if (bitrateBps <= 0) {
- throw new IllegalArgumentException("Bitrate must be larger than 0");
- }
- trackFormat.bitrateBps = bitrateBps;
- }
-
- if (format.containsKey(MediaFormat.KEY_WIDTH) && format.containsKey(
- MediaFormat.KEY_HEIGHT)) {
- int width = format.getInteger(MediaFormat.KEY_WIDTH);
- int height = format.getInteger(MediaFormat.KEY_HEIGHT);
- if (width <= 0 || height <= 0) {
- throw new IllegalArgumentException("Width and height must be larger than 0");
- }
- // TODO: Validate the aspect ratio after adding scaling.
- trackFormat.width = width;
- trackFormat.height = height;
- }
-
- if (format.containsKey(MediaFormat.KEY_PROFILE)) {
- int profile = format.getInteger(MediaFormat.KEY_PROFILE);
- if (profile <= 0) {
- throw new IllegalArgumentException("Invalid codec profile");
- }
- // TODO: Validate the profile according to codec type.
- trackFormat.profile = profile;
- }
-
- if (format.containsKey(MediaFormat.KEY_LEVEL)) {
- int level = format.getInteger(MediaFormat.KEY_LEVEL);
- if (level <= 0) {
- throw new IllegalArgumentException("Invalid codec level");
- }
- // TODO: Validate the level according to codec type.
- trackFormat.level = level;
- }
-
- return trackFormat;
- }
-
- /**
- * Builder class for {@link VideoTranscodingRequest}.
- */
- public static final class Builder extends
- TranscodingRequest.Builder<VideoTranscodingRequest.Builder> {
- /**
- * Desired output video format of the destination file.
- * <p> If this is null, source file's video track will be passed through and
- * copied to the destination file.
- */
- private @Nullable MediaFormat mVideoTrackFormat = null;
-
- /**
- * Desired output audio format of the destination file.
- * <p> If this is null, source file's audio track will be passed through and copied
- * to the destination file.
- */
- private @Nullable MediaFormat mAudioTrackFormat = null;
-
- /**
- * Creates a builder for building {@link VideoTranscodingRequest}s.
- *
- * <p> Client could only specify the settings that matters to them, e.g. codec format or
- * bitrate. And by default, transcoding will preserve the original video's settings
- * (bitrate, framerate, resolution) if not provided.
- * <p>Note that some settings may silently fail to apply if the device does not support
- * them.
- * @param sourceUri Content uri for the source media file.
- * @param destinationUri Content uri for the destination media file.
- * @param videoFormat MediaFormat containing the settings that client wants override in
- * the original video's video track.
- * @throws IllegalArgumentException if videoFormat is invalid.
- */
- public Builder(@NonNull Uri sourceUri, @NonNull Uri destinationUri,
- @NonNull MediaFormat videoFormat) {
- super(TRANSCODING_TYPE_VIDEO, sourceUri, destinationUri);
- setVideoTrackFormat(videoFormat);
- }
-
- @Override
- @NonNull
- public Builder setClientUid(int uid) {
- super.setClientUid(uid);
- return self();
- }
-
- @Override
- @NonNull
- public Builder setClientPid(int pid) {
- super.setClientPid(pid);
- return self();
- }
-
- @Override
- @NonNull
- public Builder setSourceFileDescriptor(@NonNull ParcelFileDescriptor fd) {
- super.setSourceFileDescriptor(fd);
- return self();
- }
-
- @Override
- @NonNull
- public Builder setDestinationFileDescriptor(@NonNull ParcelFileDescriptor fd) {
- super.setDestinationFileDescriptor(fd);
- return self();
- }
-
- private void setVideoTrackFormat(@NonNull MediaFormat videoFormat) {
- if (videoFormat == null) {
- throw new IllegalArgumentException("videoFormat must not be null");
- }
-
- // Check if the MediaFormat is for video by looking at the MIME type.
- String mime = videoFormat.containsKey(MediaFormat.KEY_MIME)
- ? videoFormat.getString(MediaFormat.KEY_MIME) : null;
- if (mime == null || !mime.startsWith("video/")) {
- throw new IllegalArgumentException("Invalid video format: wrong mime type");
- }
-
- mVideoTrackFormat = videoFormat;
- }
-
- /**
- * @return a new {@link TranscodingRequest} instance successfully initialized
- * with all the parameters set on this <code>Builder</code>.
- * @throws UnsupportedOperationException if the parameters set on the
- * <code>Builder</code> were incompatible, or
- * if they are not supported by the
- * device.
- */
- @NonNull
- public VideoTranscodingRequest build() {
- return new VideoTranscodingRequest(this);
- }
-
- @Override
- VideoTranscodingRequest.Builder self() {
- return this;
- }
- }
- }
-
- /**
- * Handle to an enqueued transcoding operation. An instance of this class represents a single
- * enqueued transcoding operation. The caller can use that instance to query the status or
- * progress, and to get the result once the operation has completed.
- */
- public static final class TranscodingSession {
- /** The session is enqueued but not yet running. */
- public static final int STATUS_PENDING = 1;
- /** The session is currently running. */
- public static final int STATUS_RUNNING = 2;
- /** The session is finished. */
- public static final int STATUS_FINISHED = 3;
- /** The session is paused. */
- public static final int STATUS_PAUSED = 4;
-
- /** @hide */
- @IntDef(prefix = { "STATUS_" }, value = {
- STATUS_PENDING,
- STATUS_RUNNING,
- STATUS_FINISHED,
- STATUS_PAUSED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Status {}
-
- /** The session does not have a result yet. */
- public static final int RESULT_NONE = 1;
- /** The session completed successfully. */
- public static final int RESULT_SUCCESS = 2;
- /** The session encountered an error while running. */
- public static final int RESULT_ERROR = 3;
- /** The session was canceled by the caller. */
- public static final int RESULT_CANCELED = 4;
-
- /** @hide */
- @IntDef(prefix = { "RESULT_" }, value = {
- RESULT_NONE,
- RESULT_SUCCESS,
- RESULT_ERROR,
- RESULT_CANCELED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Result {}
-
-
- // The error code exposed here should be in sync with:
- // frameworks/av/media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
- /** @hide */
- @IntDef(prefix = { "TRANSCODING_SESSION_ERROR_" }, value = {
- ERROR_NONE,
- ERROR_DROPPED_BY_SERVICE,
- ERROR_SERVICE_DIED})
- @Retention(RetentionPolicy.SOURCE)
- public @interface TranscodingSessionErrorCode{}
- /**
- * Constant indicating that no error occurred.
- */
- public static final int ERROR_NONE = 0;
-
- /**
- * Constant indicating that the session is dropped by Transcoding service due to hitting
- * the limit, e.g. too many back to back transcoding happen in a short time frame.
- */
- public static final int ERROR_DROPPED_BY_SERVICE = 1;
-
- /**
- * Constant indicating the backing transcoding service is died. Client should enqueue the
- * the request again.
- */
- public static final int ERROR_SERVICE_DIED = 2;
-
- /** Listener that gets notified when the progress changes. */
- @FunctionalInterface
- public interface OnProgressUpdateListener {
- /**
- * Called when the progress changes. The progress is in percentage between 0 and 1,
- * where 0 means the session has not yet started and 100 means that it has finished.
- *
- * @param session The session associated with the progress.
- * @param progress The new progress ranging from 0 ~ 100 inclusive.
- */
- void onProgressUpdate(@NonNull TranscodingSession session,
- @IntRange(from = 0, to = 100) int progress);
- }
-
- private final MediaTranscodingManager mManager;
- private Executor mListenerExecutor;
- private OnTranscodingFinishedListener mListener;
- private int mSessionId = -1;
- // Lock for internal state.
- private final Object mLock = new Object();
- @GuardedBy("mLock")
- private Executor mProgressUpdateExecutor = null;
- @GuardedBy("mLock")
- private OnProgressUpdateListener mProgressUpdateListener = null;
- @GuardedBy("mLock")
- private int mProgress = 0;
- @GuardedBy("mLock")
- private int mProgressUpdateInterval = 0;
- @GuardedBy("mLock")
- private @Status int mStatus = STATUS_PENDING;
- @GuardedBy("mLock")
- private @Result int mResult = RESULT_NONE;
- @GuardedBy("mLock")
- private @TranscodingSessionErrorCode int mErrorCode = ERROR_NONE;
- @GuardedBy("mLock")
- private boolean mHasRetried = false;
- // The original request that associated with this session.
- private final TranscodingRequest mRequest;
-
- private TranscodingSession(
- @NonNull MediaTranscodingManager manager,
- @NonNull TranscodingRequest request,
- @NonNull TranscodingSessionParcel parcel,
- @NonNull @CallbackExecutor Executor executor,
- @NonNull OnTranscodingFinishedListener listener) {
- Objects.requireNonNull(manager, "manager must not be null");
- Objects.requireNonNull(parcel, "parcel must not be null");
- Objects.requireNonNull(executor, "listenerExecutor must not be null");
- Objects.requireNonNull(listener, "listener must not be null");
- mManager = manager;
- mSessionId = parcel.sessionId;
- mListenerExecutor = executor;
- mListener = listener;
- mRequest = request;
- }
-
- /**
- * Set a progress listener.
- * @param executor The executor on which listener will be invoked.
- * @param listener The progress listener.
- */
- public void setOnProgressUpdateListener(
- @NonNull @CallbackExecutor Executor executor,
- @Nullable OnProgressUpdateListener listener) {
- synchronized (mLock) {
- Objects.requireNonNull(executor, "listenerExecutor must not be null");
- Objects.requireNonNull(listener, "listener must not be null");
- mProgressUpdateExecutor = executor;
- mProgressUpdateListener = listener;
- }
- }
-
- private void updateStatusAndResult(@Status int sessionStatus,
- @Result int sessionResult, @TranscodingSessionErrorCode int errorCode) {
- synchronized (mLock) {
- mStatus = sessionStatus;
- mResult = sessionResult;
- mErrorCode = errorCode;
- }
- }
-
- /**
- * Retrieve the error code associated with the RESULT_ERROR.
- */
- public @TranscodingSessionErrorCode int getErrorCode() {
- synchronized (mLock) {
- return mErrorCode;
- }
- }
-
- /**
- * Resubmit the transcoding session to the service.
- * Note that only the session that fails or gets cancelled could be retried and each session
- * could be retried only once. After that, Client need to enqueue a new request if they want
- * to try again.
- *
- * @return true if successfully resubmit the job to service. False otherwise.
- * @throws UnsupportedOperationException if the retry could not be fulfilled.
- * @hide
- */
- public boolean retry() {
- return retryInternal(true /*setHasRetried*/);
- }
-
- // TODO(hkuang): Add more test for it.
- private boolean retryInternal(boolean setHasRetried) {
- synchronized (mLock) {
- if (mStatus == STATUS_PENDING || mStatus == STATUS_RUNNING) {
- throw new UnsupportedOperationException(
- "Failed to retry as session is in processing");
- }
-
- if (mHasRetried) {
- throw new UnsupportedOperationException("Session has been retried already");
- }
-
- // Get the client interface.
- ITranscodingClient client = mManager.getTranscodingClient();
- if (client == null) {
- Log.e(TAG, "Service rebooting. Try again later");
- return false;
- }
-
- synchronized (mManager.mPendingTranscodingSessions) {
- try {
- // Submits the request to MediaTranscoding service.
- TranscodingSessionParcel sessionParcel = new TranscodingSessionParcel();
- if (!client.submitRequest(mRequest.writeToParcel(mManager.mContext),
- sessionParcel)) {
- mHasRetried = true;
- throw new UnsupportedOperationException("Failed to enqueue request");
- }
-
- // Replace the old session id wit the new one.
- mSessionId = sessionParcel.sessionId;
- // Adds the new session back into pending sessions.
- mManager.mPendingTranscodingSessions.put(mSessionId, this);
- } catch (RemoteException re) {
- return false;
- }
- mStatus = STATUS_PENDING;
- mHasRetried = setHasRetried ? true : false;
- }
- }
- return true;
- }
-
- /**
- * Cancels the transcoding session and notify the listener.
- * If the session happened to finish before being canceled this call is effectively a no-op
- * and will not update the result in that case.
- */
- public void cancel() {
- synchronized (mLock) {
- // Check if the session is finished already.
- if (mStatus != STATUS_FINISHED) {
- try {
- ITranscodingClient client = mManager.getTranscodingClient();
- // The client may be gone.
- if (client != null) {
- client.cancelSession(mSessionId);
- }
- } catch (RemoteException re) {
- //TODO(hkuang): Find out what to do if failing to cancel the session.
- Log.e(TAG, "Failed to cancel the session due to exception: " + re);
- }
- mStatus = STATUS_FINISHED;
- mResult = RESULT_CANCELED;
-
- // Notifies client the session is canceled.
- mListenerExecutor.execute(() -> mListener.onTranscodingFinished(this));
- }
- }
- }
-
- /**
- * Gets the progress of the transcoding session. The progress is between 0 and 100, where 0
- * means that the session has not yet started and 100 means that it is finished. For the
- * cancelled session, the progress will be the last updated progress before it is cancelled.
- * @return The progress.
- */
- @IntRange(from = 0, to = 100)
- public int getProgress() {
- synchronized (mLock) {
- return mProgress;
- }
- }
-
- /**
- * Gets the status of the transcoding session.
- * @return The status.
- */
- public @Status int getStatus() {
- synchronized (mLock) {
- return mStatus;
- }
- }
-
- /**
- * Adds a client uid that is also waiting for this transcoding session.
- * <p>
- * Only privilege caller with android.permission.WRITE_MEDIA_STORAGE could add the
- * uid. Note that the permission check happens on the service side upon starting the
- * transcoding. If the client does not have the permission, the transcoding will fail.
- * @param uid the additional client uid to be added.
- * @return true if successfully added, false otherwise.
- */
- public boolean addClientUid(int uid) {
- if (uid < 0) {
- throw new IllegalArgumentException("Invalid Uid");
- }
-
- // Get the client interface.
- ITranscodingClient client = mManager.getTranscodingClient();
- if (client == null) {
- Log.e(TAG, "Service is dead...");
- return false;
- }
-
- try {
- if (!client.addClientUid(mSessionId, uid)) {
- Log.e(TAG, "Failed to add client uid");
- return false;
- }
- } catch (Exception ex) {
- Log.e(TAG, "Failed to get client uids due to " + ex);
- return false;
- }
- return true;
- }
-
- /**
- * Query all the client that waiting for this transcoding session
- * @return a list containing all the client uids.
- */
- @NonNull
- public List<Integer> getClientUids() {
- List<Integer> uidList = new ArrayList<Integer>();
-
- // Get the client interface.
- ITranscodingClient client = mManager.getTranscodingClient();
- if (client == null) {
- Log.e(TAG, "Service is dead...");
- return uidList;
- }
-
- try {
- int[] clientUids = client.getClientUids(mSessionId);
- for (int i : clientUids) {
- uidList.add(i);
- }
- } catch (Exception ex) {
- Log.e(TAG, "Failed to get client uids due to " + ex);
- }
-
- return uidList;
- }
-
- /**
- * Gets sessionId of the transcoding session.
- * @return session id.
- */
- public int getSessionId() {
- return mSessionId;
- }
-
- /**
- * Gets the result of the transcoding session.
- * @return The result.
- */
- public @Result int getResult() {
- synchronized (mLock) {
- return mResult;
- }
- }
-
- @Override
- public String toString() {
- String result;
- String status;
-
- switch (mResult) {
- case RESULT_NONE:
- result = "RESULT_NONE";
- break;
- case RESULT_SUCCESS:
- result = "RESULT_SUCCESS";
- break;
- case RESULT_ERROR:
- result = "RESULT_ERROR(" + mErrorCode + ")";
- break;
- case RESULT_CANCELED:
- result = "RESULT_CANCELED";
- break;
- default:
- result = String.valueOf(mResult);
- break;
- }
-
- switch (mStatus) {
- case STATUS_PENDING:
- status = "STATUS_PENDING";
- break;
- case STATUS_PAUSED:
- status = "STATUS_PAUSED";
- break;
- case STATUS_RUNNING:
- status = "STATUS_RUNNING";
- break;
- case STATUS_FINISHED:
- status = "STATUS_FINISHED";
- break;
- default:
- status = String.valueOf(mStatus);
- break;
- }
- return String.format(" session: {id: %d, status: %s, result: %s, progress: %d}",
- mSessionId, status, result, mProgress);
- }
-
- private void updateProgress(int newProgress) {
- synchronized (mLock) {
- mProgress = newProgress;
- }
- }
-
- private void updateStatus(int newStatus) {
- synchronized (mLock) {
- mStatus = newStatus;
- }
- }
- }
-
- private ITranscodingClient getTranscodingClient() {
- synchronized (mLock) {
- return mTranscodingClient;
- }
- }
-
- /**
- * Enqueues a TranscodingRequest for execution.
- * <p> Upon successfully accepting the request, MediaTranscodingManager will return a
- * {@link TranscodingSession} to the client. Client should use {@link TranscodingSession} to
- * track the progress and get the result.
- * <p> MediaTranscodingManager will return null if fails to accept the request due to service
- * rebooting. Client could retry again after receiving null.
- *
- * @param transcodingRequest The TranscodingRequest to enqueue.
- * @param listenerExecutor Executor on which the listener is notified.
- * @param listener Listener to get notified when the transcoding session is finished.
- * @return A TranscodingSession for this operation.
- * @throws UnsupportedOperationException if the request could not be fulfilled.
- */
- @Nullable
- public TranscodingSession enqueueRequest(
- @NonNull TranscodingRequest transcodingRequest,
- @NonNull @CallbackExecutor Executor listenerExecutor,
- @NonNull OnTranscodingFinishedListener listener) {
- Log.i(TAG, "enqueueRequest called.");
- Objects.requireNonNull(transcodingRequest, "transcodingRequest must not be null");
- Objects.requireNonNull(listenerExecutor, "listenerExecutor must not be null");
- Objects.requireNonNull(listener, "listener must not be null");
-
- // Converts the request to TranscodingRequestParcel.
- TranscodingRequestParcel requestParcel = transcodingRequest.writeToParcel(mContext);
-
- Log.i(TAG, "Getting transcoding request " + transcodingRequest.getSourceUri());
-
- // Submits the request to MediaTranscoding service.
- try {
- TranscodingSessionParcel sessionParcel = new TranscodingSessionParcel();
- // Synchronizes the access to mPendingTranscodingSessions to make sure the session Id is
- // inserted in the mPendingTranscodingSessions in the callback handler.
- synchronized (mPendingTranscodingSessions) {
- synchronized (mLock) {
- if (mTranscodingClient == null) {
- // Try to register with the service again.
- IMediaTranscodingService service = getService(false /*retry*/);
- if (service == null) {
- Log.w(TAG, "Service rebooting. Try again later");
- return null;
- }
- mTranscodingClient = registerClient(service);
- // If still fails, throws an exception to tell client to try later.
- if (mTranscodingClient == null) {
- Log.w(TAG, "Service rebooting. Try again later");
- return null;
- }
- }
-
- if (!mTranscodingClient.submitRequest(requestParcel, sessionParcel)) {
- throw new UnsupportedOperationException("Failed to enqueue request");
- }
- }
-
- // Wraps the TranscodingSessionParcel into a TranscodingSession and returns it to
- // client for tracking.
- TranscodingSession session = new TranscodingSession(this, transcodingRequest,
- sessionParcel,
- listenerExecutor,
- listener);
-
- // Adds the new session into pending sessions.
- mPendingTranscodingSessions.put(session.getSessionId(), session);
- return session;
- }
- } catch (RemoteException ex) {
- Log.w(TAG, "Service rebooting. Try again later");
- return null;
- } catch (ServiceSpecificException ex) {
- throw new UnsupportedOperationException(
- "Failed to submit request to Transcoding service. Error: " + ex);
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/ProxyDataSourceCallback.java b/apex/media/framework/java/android/media/ProxyDataSourceCallback.java
deleted file mode 100644
index 14d3ce8..0000000
--- a/apex/media/framework/java/android/media/ProxyDataSourceCallback.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.os.ParcelFileDescriptor;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.util.Log;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * A DataSourceCallback that is backed by a ParcelFileDescriptor.
- */
-class ProxyDataSourceCallback extends DataSourceCallback {
- private static final String TAG = "TestDataSourceCallback";
-
- ParcelFileDescriptor mPFD;
- FileDescriptor mFD;
-
- ProxyDataSourceCallback(ParcelFileDescriptor pfd) throws IOException {
- mPFD = pfd.dup();
- mFD = mPFD.getFileDescriptor();
- }
-
- @Override
- public synchronized int readAt(long position, byte[] buffer, int offset, int size)
- throws IOException {
- try {
- Os.lseek(mFD, position, OsConstants.SEEK_SET);
- int ret = Os.read(mFD, buffer, offset, size);
- return (ret == 0) ? END_OF_STREAM : ret;
- } catch (ErrnoException e) {
- throw new IOException(e);
- }
- }
-
- @Override
- public synchronized long getSize() throws IOException {
- return mPFD.getStatSize();
- }
-
- @Override
- public synchronized void close() {
- try {
- mPFD.close();
- } catch (IOException e) {
- Log.e(TAG, "Failed to close the PFD.", e);
- }
- }
-}
-
diff --git a/apex/media/framework/java/android/media/RoutingDelegate.java b/apex/media/framework/java/android/media/RoutingDelegate.java
deleted file mode 100644
index 2359813..0000000
--- a/apex/media/framework/java/android/media/RoutingDelegate.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2018 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.media;
-
-import android.os.Handler;
-
-class RoutingDelegate implements AudioRouting.OnRoutingChangedListener {
- private AudioRouting mAudioRouting;
- private AudioRouting.OnRoutingChangedListener mOnRoutingChangedListener;
- private Handler mHandler;
-
- RoutingDelegate(final AudioRouting audioRouting,
- final AudioRouting.OnRoutingChangedListener listener,
- Handler handler) {
- mAudioRouting = audioRouting;
- mOnRoutingChangedListener = listener;
- mHandler = handler;
- }
-
- public AudioRouting.OnRoutingChangedListener getListener() {
- return mOnRoutingChangedListener;
- }
-
- public Handler getHandler() {
- return mHandler;
- }
-
- @Override
- public void onRoutingChanged(AudioRouting router) {
- if (mOnRoutingChangedListener != null) {
- mOnRoutingChangedListener.onRoutingChanged(mAudioRouting);
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/Session2Command.java b/apex/media/framework/java/android/media/Session2Command.java
deleted file mode 100644
index 26f4568..0000000
--- a/apex/media/framework/java/android/media/Session2Command.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.util.Objects;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Define a command that a {@link MediaController2} can send to a {@link MediaSession2}.
- * <p>
- * If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
- * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
- * {@link #getCustomAction()} shouldn't be {@code null}.
- * <p>
- * Refer to the
- * <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a>
- * class for the list of valid commands.
- */
-public final class Session2Command implements Parcelable {
- /**
- * Command code for the custom command which can be defined by string action in the
- * {@link Session2Command}.
- */
- public static final int COMMAND_CODE_CUSTOM = 0;
-
- public static final @android.annotation.NonNull Parcelable.Creator<Session2Command> CREATOR =
- new Parcelable.Creator<Session2Command>() {
- @Override
- public Session2Command createFromParcel(Parcel in) {
- return new Session2Command(in);
- }
-
- @Override
- public Session2Command[] newArray(int size) {
- return new Session2Command[size];
- }
- };
-
- private final int mCommandCode;
- // Nonnull if it's custom command
- private final String mCustomAction;
- private final Bundle mCustomExtras;
-
- /**
- * Constructor for creating a command predefined in AndroidX media2.
- *
- * @param commandCode A command code for a command predefined in AndroidX media2.
- */
- public Session2Command(int commandCode) {
- if (commandCode == COMMAND_CODE_CUSTOM) {
- throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
- }
- mCommandCode = commandCode;
- mCustomAction = null;
- mCustomExtras = null;
- }
-
- /**
- * Constructor for creating a custom command.
- *
- * @param action The action of this custom command.
- * @param extras An extra bundle for this custom command.
- */
- public Session2Command(@NonNull String action, @Nullable Bundle extras) {
- if (action == null) {
- throw new IllegalArgumentException("action shouldn't be null");
- }
- mCommandCode = COMMAND_CODE_CUSTOM;
- mCustomAction = action;
- mCustomExtras = extras;
- }
-
- /**
- * Used by parcelable creator.
- */
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- Session2Command(Parcel in) {
- mCommandCode = in.readInt();
- mCustomAction = in.readString();
- mCustomExtras = in.readBundle();
- }
-
- /**
- * Gets the command code of a predefined command.
- * This will return {@link #COMMAND_CODE_CUSTOM} for a custom command.
- */
- public int getCommandCode() {
- return mCommandCode;
- }
-
- /**
- * Gets the action of a custom command.
- * This will return {@code null} for a predefined command.
- */
- @Nullable
- public String getCustomAction() {
- return mCustomAction;
- }
-
- /**
- * Gets the extra bundle of a custom command.
- * This will return {@code null} for a predefined command.
- */
- @Nullable
- public Bundle getCustomExtras() {
- return mCustomExtras;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- if (dest == null) {
- throw new IllegalArgumentException("parcel shouldn't be null");
- }
- dest.writeInt(mCommandCode);
- dest.writeString(mCustomAction);
- dest.writeBundle(mCustomExtras);
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (!(obj instanceof Session2Command)) {
- return false;
- }
- Session2Command other = (Session2Command) obj;
- return mCommandCode == other.mCommandCode
- && TextUtils.equals(mCustomAction, other.mCustomAction);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mCustomAction, mCommandCode);
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Contains the result of {@link Session2Command}.
- */
- public static final class Result {
- private final int mResultCode;
- private final Bundle mResultData;
-
- /**
- * Result code representing that the command is skipped or canceled. For an example, a seek
- * command can be skipped if it is followed by another seek command.
- */
- public static final int RESULT_INFO_SKIPPED = 1;
-
- /**
- * Result code representing that the command is successfully completed.
- */
- public static final int RESULT_SUCCESS = 0;
-
- /**
- * Result code represents that call is ended with an unknown error.
- */
- public static final int RESULT_ERROR_UNKNOWN_ERROR = -1;
-
- /**
- * Constructor of {@link Result}.
- *
- * @param resultCode result code
- * @param resultData result data
- */
- public Result(int resultCode, @Nullable Bundle resultData) {
- mResultCode = resultCode;
- mResultData = resultData;
- }
-
- /**
- * Returns the result code.
- */
- public int getResultCode() {
- return mResultCode;
- }
-
- /**
- * Returns the result data.
- */
- @Nullable
- public Bundle getResultData() {
- return mResultData;
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/Session2CommandGroup.java b/apex/media/framework/java/android/media/Session2CommandGroup.java
deleted file mode 100644
index 13aabfc..0000000
--- a/apex/media/framework/java/android/media/Session2CommandGroup.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import static android.media.Session2Command.COMMAND_CODE_CUSTOM;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * A set of {@link Session2Command} which represents a command group.
- */
-public final class Session2CommandGroup implements Parcelable {
- private static final String TAG = "Session2CommandGroup";
-
- public static final @android.annotation.NonNull Parcelable.Creator<Session2CommandGroup>
- CREATOR = new Parcelable.Creator<Session2CommandGroup>() {
- @Override
- public Session2CommandGroup createFromParcel(Parcel in) {
- return new Session2CommandGroup(in);
- }
-
- @Override
- public Session2CommandGroup[] newArray(int size) {
- return new Session2CommandGroup[size];
- }
- };
-
- Set<Session2Command> mCommands = new HashSet<>();
-
- /**
- * Creates a new Session2CommandGroup with commands copied from another object.
- *
- * @param commands The collection of commands to copy.
- */
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- Session2CommandGroup(@Nullable Collection<Session2Command> commands) {
- if (commands != null) {
- mCommands.addAll(commands);
- }
- }
-
- /**
- * Used by parcelable creator.
- */
- @SuppressWarnings("WeakerAccess") /* synthetic access */
- Session2CommandGroup(Parcel in) {
- Parcelable[] commands = in.readParcelableArray(Session2Command.class.getClassLoader());
- if (commands != null) {
- for (Parcelable command : commands) {
- mCommands.add((Session2Command) command);
- }
- }
- }
-
- /**
- * Checks whether this command group has a command that matches given {@code command}.
- *
- * @param command A command to find. Shouldn't be {@code null}.
- */
- public boolean hasCommand(@NonNull Session2Command command) {
- if (command == null) {
- throw new IllegalArgumentException("command shouldn't be null");
- }
- return mCommands.contains(command);
- }
-
- /**
- * Checks whether this command group has a command that matches given {@code commandCode}.
- *
- * @param commandCode A command code to find.
- * Shouldn't be {@link Session2Command#COMMAND_CODE_CUSTOM}.
- */
- public boolean hasCommand(int commandCode) {
- if (commandCode == COMMAND_CODE_CUSTOM) {
- throw new IllegalArgumentException("Use hasCommand(Command) for custom command");
- }
- for (Session2Command command : mCommands) {
- if (command.getCommandCode() == commandCode) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Gets all commands of this command group.
- */
- @NonNull
- public Set<Session2Command> getCommands() {
- return new HashSet<>(mCommands);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- if (dest == null) {
- throw new IllegalArgumentException("parcel shouldn't be null");
- }
- dest.writeParcelableArray(mCommands.toArray(new Session2Command[0]), 0);
- }
-
- /**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Builds a {@link Session2CommandGroup} object.
- */
- public static final class Builder {
- private Set<Session2Command> mCommands;
-
- public Builder() {
- mCommands = new HashSet<>();
- }
-
- /**
- * Creates a new builder for {@link Session2CommandGroup} with commands copied from another
- * {@link Session2CommandGroup} object.
- * @param commandGroup
- */
- public Builder(@NonNull Session2CommandGroup commandGroup) {
- if (commandGroup == null) {
- throw new IllegalArgumentException("command group shouldn't be null");
- }
- mCommands = commandGroup.getCommands();
- }
-
- /**
- * Adds a command to this command group.
- *
- * @param command A command to add. Shouldn't be {@code null}.
- */
- @NonNull
- public Builder addCommand(@NonNull Session2Command command) {
- if (command == null) {
- throw new IllegalArgumentException("command shouldn't be null");
- }
- mCommands.add(command);
- return this;
- }
-
- /**
- * Removes a command from this group which matches given {@code command}.
- *
- * @param command A command to find. Shouldn't be {@code null}.
- */
- @NonNull
- public Builder removeCommand(@NonNull Session2Command command) {
- if (command == null) {
- throw new IllegalArgumentException("command shouldn't be null");
- }
- mCommands.remove(command);
- return this;
- }
-
- /**
- * Builds {@link Session2CommandGroup}.
- *
- * @return a new {@link Session2CommandGroup}.
- */
- @NonNull
- public Session2CommandGroup build() {
- return new Session2CommandGroup(mCommands);
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/Session2Link.java b/apex/media/framework/java/android/media/Session2Link.java
deleted file mode 100644
index 6e550e8..0000000
--- a/apex/media/framework/java/android/media/Session2Link.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import android.annotation.NonNull;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-import java.util.Objects;
-
-/**
- * Handles incoming commands from {@link MediaController2} to {@link MediaSession2}.
- * @hide
- */
-// @SystemApi
-public final class Session2Link implements Parcelable {
- private static final String TAG = "Session2Link";
- private static final boolean DEBUG = MediaSession2.DEBUG;
-
- public static final @android.annotation.NonNull Parcelable.Creator<Session2Link> CREATOR =
- new Parcelable.Creator<Session2Link>() {
- @Override
- public Session2Link createFromParcel(Parcel in) {
- return new Session2Link(in);
- }
-
- @Override
- public Session2Link[] newArray(int size) {
- return new Session2Link[size];
- }
- };
-
- private final MediaSession2 mSession;
- private final IMediaSession2 mISession;
-
- public Session2Link(MediaSession2 session) {
- mSession = session;
- mISession = new Session2Stub();
- }
-
- Session2Link(Parcel in) {
- mSession = null;
- mISession = IMediaSession2.Stub.asInterface(in.readStrongBinder());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mISession.asBinder());
- }
-
- @Override
- public int hashCode() {
- return mISession.asBinder().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Session2Link)) {
- return false;
- }
- Session2Link other = (Session2Link) obj;
- return Objects.equals(mISession.asBinder(), other.mISession.asBinder());
- }
-
- /** Link to death with mISession */
- public void linkToDeath(@NonNull IBinder.DeathRecipient recipient, int flags) {
- if (mISession != null) {
- try {
- mISession.asBinder().linkToDeath(recipient, flags);
- } catch (RemoteException e) {
- if (DEBUG) {
- Log.d(TAG, "Session died too early.", e);
- }
- }
- }
- }
-
- /** Unlink to death with mISession */
- public boolean unlinkToDeath(@NonNull IBinder.DeathRecipient recipient, int flags) {
- if (mISession != null) {
- return mISession.asBinder().unlinkToDeath(recipient, flags);
- }
- return true;
- }
-
- /** Interface method for IMediaSession2.connect */
- public void connect(final Controller2Link caller, int seq, Bundle connectionRequest) {
- try {
- mISession.connect(caller, seq, connectionRequest);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Interface method for IMediaSession2.disconnect */
- public void disconnect(final Controller2Link caller, int seq) {
- try {
- mISession.disconnect(caller, seq);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Interface method for IMediaSession2.sendSessionCommand */
- public void sendSessionCommand(final Controller2Link caller, final int seq,
- final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
- try {
- mISession.sendSessionCommand(caller, seq, command, args, resultReceiver);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Interface method for IMediaSession2.sendSessionCommand */
- public void cancelSessionCommand(final Controller2Link caller, final int seq) {
- try {
- mISession.cancelSessionCommand(caller, seq);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Stub implementation for IMediaSession2.connect */
- public void onConnect(final Controller2Link caller, int pid, int uid, int seq,
- Bundle connectionRequest) {
- mSession.onConnect(caller, pid, uid, seq, connectionRequest);
- }
-
- /** Stub implementation for IMediaSession2.disconnect */
- public void onDisconnect(final Controller2Link caller, int seq) {
- mSession.onDisconnect(caller, seq);
- }
-
- /** Stub implementation for IMediaSession2.sendSessionCommand */
- public void onSessionCommand(final Controller2Link caller, final int seq,
- final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
- mSession.onSessionCommand(caller, seq, command, args, resultReceiver);
- }
-
- /** Stub implementation for IMediaSession2.cancelSessionCommand */
- public void onCancelCommand(final Controller2Link caller, final int seq) {
- mSession.onCancelCommand(caller, seq);
- }
-
- private class Session2Stub extends IMediaSession2.Stub {
- @Override
- public void connect(final Controller2Link caller, int seq, Bundle connectionRequest) {
- if (caller == null || connectionRequest == null) {
- return;
- }
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
- try {
- Session2Link.this.onConnect(caller, pid, uid, seq, connectionRequest);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void disconnect(final Controller2Link caller, int seq) {
- if (caller == null) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- Session2Link.this.onDisconnect(caller, seq);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void sendSessionCommand(final Controller2Link caller, final int seq,
- final Session2Command command, final Bundle args, ResultReceiver resultReceiver) {
- if (caller == null) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- Session2Link.this.onSessionCommand(caller, seq, command, args, resultReceiver);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void cancelSessionCommand(final Controller2Link caller, final int seq) {
- if (caller == null) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- Session2Link.this.onCancelCommand(caller, seq);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
- }
-}
diff --git a/apex/media/framework/java/android/media/Session2Token.java b/apex/media/framework/java/android/media/Session2Token.java
deleted file mode 100644
index aae2e1b..0000000
--- a/apex/media/framework/java/android/media/Session2Token.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright 2018 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.media;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * This API is not generally intended for third party application developers.
- * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
- * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
- * Library</a> for consistent behavior across all devices.
- * <p>
- * Represents an ongoing {@link MediaSession2} or a {@link MediaSession2Service}.
- * If it's representing a session service, it may not be ongoing.
- * <p>
- * This may be passed to apps by the session owner to allow them to create a
- * {@link MediaController2} to communicate with the session.
- * <p>
- * It can be also obtained by {@link android.media.session.MediaSessionManager}.
- */
-public final class Session2Token implements Parcelable {
- private static final String TAG = "Session2Token";
-
- public static final @android.annotation.NonNull Creator<Session2Token> CREATOR =
- new Creator<Session2Token>() {
- @Override
- public Session2Token createFromParcel(Parcel p) {
- return new Session2Token(p);
- }
-
- @Override
- public Session2Token[] newArray(int size) {
- return new Session2Token[size];
- }
- };
-
- /**
- * @hide
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = "TYPE_", value = {TYPE_SESSION, TYPE_SESSION_SERVICE})
- public @interface TokenType {
- }
-
- /**
- * Type for {@link MediaSession2}.
- */
- public static final int TYPE_SESSION = 0;
-
- /**
- * Type for {@link MediaSession2Service}.
- */
- public static final int TYPE_SESSION_SERVICE = 1;
-
- private final int mUid;
- @TokenType
- private final int mType;
- private final String mPackageName;
- private final String mServiceName;
- private final Session2Link mSessionLink;
- private final ComponentName mComponentName;
- private final Bundle mExtras;
-
- /**
- * Constructor for the token with type {@link #TYPE_SESSION_SERVICE}.
- *
- * @param context The context.
- * @param serviceComponent The component name of the service.
- */
- public Session2Token(@NonNull Context context, @NonNull ComponentName serviceComponent) {
- if (context == null) {
- throw new IllegalArgumentException("context shouldn't be null");
- }
- if (serviceComponent == null) {
- throw new IllegalArgumentException("serviceComponent shouldn't be null");
- }
-
- final PackageManager manager = context.getPackageManager();
- final int uid = getUid(manager, serviceComponent.getPackageName());
-
- if (!isInterfaceDeclared(manager, MediaSession2Service.SERVICE_INTERFACE,
- serviceComponent)) {
- Log.w(TAG, serviceComponent + " doesn't implement MediaSession2Service.");
- }
- mComponentName = serviceComponent;
- mPackageName = serviceComponent.getPackageName();
- mServiceName = serviceComponent.getClassName();
- mUid = uid;
- mType = TYPE_SESSION_SERVICE;
- mSessionLink = null;
- mExtras = Bundle.EMPTY;
- }
-
- Session2Token(int uid, int type, String packageName, Session2Link sessionLink,
- @NonNull Bundle tokenExtras) {
- mUid = uid;
- mType = type;
- mPackageName = packageName;
- mServiceName = null;
- mComponentName = null;
- mSessionLink = sessionLink;
- mExtras = tokenExtras;
- }
-
- Session2Token(Parcel in) {
- mUid = in.readInt();
- mType = in.readInt();
- mPackageName = in.readString();
- mServiceName = in.readString();
- mSessionLink = in.readParcelable(null);
- mComponentName = ComponentName.unflattenFromString(in.readString());
-
- Bundle extras = in.readBundle();
- if (extras == null) {
- Log.w(TAG, "extras shouldn't be null.");
- extras = Bundle.EMPTY;
- } else if (MediaSession2.hasCustomParcelable(extras)) {
- Log.w(TAG, "extras contain custom parcelable. Ignoring.");
- extras = Bundle.EMPTY;
- }
- mExtras = extras;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mUid);
- dest.writeInt(mType);
- dest.writeString(mPackageName);
- dest.writeString(mServiceName);
- dest.writeParcelable(mSessionLink, flags);
- dest.writeString(mComponentName == null ? "" : mComponentName.flattenToString());
- dest.writeBundle(mExtras);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mType, mUid, mPackageName, mServiceName, mSessionLink);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Session2Token)) {
- return false;
- }
- Session2Token other = (Session2Token) obj;
- return mUid == other.mUid
- && TextUtils.equals(mPackageName, other.mPackageName)
- && TextUtils.equals(mServiceName, other.mServiceName)
- && mType == other.mType
- && Objects.equals(mSessionLink, other.mSessionLink);
- }
-
- @Override
- public String toString() {
- return "Session2Token {pkg=" + mPackageName + " type=" + mType
- + " service=" + mServiceName + " Session2Link=" + mSessionLink + "}";
- }
-
- /**
- * @return uid of the session
- */
- public int getUid() {
- return mUid;
- }
-
- /**
- * @return package name of the session
- */
- @NonNull
- public String getPackageName() {
- return mPackageName;
- }
-
- /**
- * @return service name of the session. Can be {@code null} for {@link #TYPE_SESSION}.
- */
- @Nullable
- public String getServiceName() {
- return mServiceName;
- }
-
- /**
- * @return type of the token
- * @see #TYPE_SESSION
- * @see #TYPE_SESSION_SERVICE
- */
- public @TokenType int getType() {
- return mType;
- }
-
- /**
- * @return extras of the token
- * @see MediaSession2.Builder#setExtras(Bundle)
- */
- @NonNull
- public Bundle getExtras() {
- return new Bundle(mExtras);
- }
-
- Session2Link getSessionLink() {
- return mSessionLink;
- }
-
- private static boolean isInterfaceDeclared(PackageManager manager, String serviceInterface,
- ComponentName serviceComponent) {
- Intent serviceIntent = new Intent(serviceInterface);
- // Use queryIntentServices to find services with MediaSession2Service.SERVICE_INTERFACE.
- // We cannot use resolveService with intent specified class name, because resolveService
- // ignores actions if Intent.setClassName() is specified.
- serviceIntent.setPackage(serviceComponent.getPackageName());
-
- List<ResolveInfo> list = manager.queryIntentServices(
- serviceIntent, PackageManager.GET_META_DATA);
- if (list != null) {
- for (int i = 0; i < list.size(); i++) {
- ResolveInfo resolveInfo = list.get(i);
- if (resolveInfo == null || resolveInfo.serviceInfo == null) {
- continue;
- }
- if (TextUtils.equals(
- resolveInfo.serviceInfo.name, serviceComponent.getClassName())) {
- return true;
- }
- }
- }
- return false;
- }
-
- private static int getUid(PackageManager manager, String packageName) {
- try {
- return manager.getApplicationInfo(packageName, 0).uid;
- } catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException("Cannot find package " + packageName);
- }
- }
-}
diff --git a/apex/media/framework/jni/android_media_MediaParserJNI.cpp b/apex/media/framework/jni/android_media_MediaParserJNI.cpp
deleted file mode 100644
index c81152c..0000000
--- a/apex/media/framework/jni/android_media_MediaParserJNI.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2020, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <jni.h>
-#include <media/MediaMetrics.h>
-
-#define JNI_FUNCTION(RETURN_TYPE, NAME, ...) \
- extern "C" { \
- JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
- ##__VA_ARGS__); \
- } \
- JNIEXPORT RETURN_TYPE Java_android_media_MediaParser_##NAME(JNIEnv* env, jobject thiz, \
- ##__VA_ARGS__)
-
-namespace {
-
-constexpr char kMediaMetricsKey[] = "mediaparser";
-
-constexpr char kAttributeLogSessionId[] = "android.media.mediaparser.logSessionId";
-constexpr char kAttributeParserName[] = "android.media.mediaparser.parserName";
-constexpr char kAttributeCreatedByName[] = "android.media.mediaparser.createdByName";
-constexpr char kAttributeParserPool[] = "android.media.mediaparser.parserPool";
-constexpr char kAttributeLastException[] = "android.media.mediaparser.lastException";
-constexpr char kAttributeResourceByteCount[] = "android.media.mediaparser.resourceByteCount";
-constexpr char kAttributeDurationMillis[] = "android.media.mediaparser.durationMillis";
-constexpr char kAttributeTrackMimeTypes[] = "android.media.mediaparser.trackMimeTypes";
-constexpr char kAttributeTrackCodecs[] = "android.media.mediaparser.trackCodecs";
-constexpr char kAttributeAlteredParameters[] = "android.media.mediaparser.alteredParameters";
-constexpr char kAttributeVideoWidth[] = "android.media.mediaparser.videoWidth";
-constexpr char kAttributeVideoHeight[] = "android.media.mediaparser.videoHeight";
-
-// Util class to handle string resource management.
-class JstringHandle {
-public:
- JstringHandle(JNIEnv* env, jstring value) : mEnv(env), mJstringValue(value) {
- mCstringValue = env->GetStringUTFChars(value, /* isCopy= */ nullptr);
- }
-
- ~JstringHandle() {
- if (mCstringValue != nullptr) {
- mEnv->ReleaseStringUTFChars(mJstringValue, mCstringValue);
- }
- }
-
- [[nodiscard]] const char* value() const {
- return mCstringValue != nullptr ? mCstringValue : "";
- }
-
- JNIEnv* mEnv;
- jstring mJstringValue;
- const char* mCstringValue;
-};
-
-} // namespace
-
-JNI_FUNCTION(void, nativeSubmitMetrics, jstring logSessionIdJstring, jstring parserNameJstring,
- jboolean createdByName, jstring parserPoolJstring, jstring lastExceptionJstring,
- jlong resourceByteCount, jlong durationMillis, jstring trackMimeTypesJstring,
- jstring trackCodecsJstring, jstring alteredParameters, jint videoWidth,
- jint videoHeight) {
- mediametrics_handle_t item(mediametrics_create(kMediaMetricsKey));
- mediametrics_setCString(item, kAttributeLogSessionId,
- JstringHandle(env, logSessionIdJstring).value());
- mediametrics_setCString(item, kAttributeParserName,
- JstringHandle(env, parserNameJstring).value());
- mediametrics_setInt32(item, kAttributeCreatedByName, createdByName ? 1 : 0);
- mediametrics_setCString(item, kAttributeParserPool,
- JstringHandle(env, parserPoolJstring).value());
- mediametrics_setCString(item, kAttributeLastException,
- JstringHandle(env, lastExceptionJstring).value());
- mediametrics_setInt64(item, kAttributeResourceByteCount, resourceByteCount);
- mediametrics_setInt64(item, kAttributeDurationMillis, durationMillis);
- mediametrics_setCString(item, kAttributeTrackMimeTypes,
- JstringHandle(env, trackMimeTypesJstring).value());
- mediametrics_setCString(item, kAttributeTrackCodecs,
- JstringHandle(env, trackCodecsJstring).value());
- mediametrics_setCString(item, kAttributeAlteredParameters,
- JstringHandle(env, alteredParameters).value());
- mediametrics_setInt32(item, kAttributeVideoWidth, videoWidth);
- mediametrics_setInt32(item, kAttributeVideoHeight, videoHeight);
- mediametrics_selfRecord(item);
- mediametrics_delete(item);
-}
diff --git a/apex/media/framework/lint-baseline.xml b/apex/media/framework/lint-baseline.xml
deleted file mode 100644
index e1b1450..0000000
--- a/apex/media/framework/lint-baseline.xml
+++ /dev/null
@@ -1,312 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `new android.media.ApplicationMediaCapabilities.Builder`"
- errorLine1=" new ApplicationMediaCapabilities.Builder();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java"
- line="208"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `new android.media.ApplicationMediaCapabilities.Builder`"
- errorLine1=" ApplicationMediaCapabilities.Builder builder = new ApplicationMediaCapabilities.Builder();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java"
- line="314"
- column="56"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `android.os.RemoteException#rethrowFromSystemServer`"
- errorLine1=" e.rethrowFromSystemServer();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaCommunicationManager.java"
- line="110"
- column="15"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `android.os.Parcel#writeParcelableCreator`"
- errorLine1=" dest.writeParcelableCreator((Parcelable) parcelable);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParceledListSlice.java"
- line="77"
- column="14"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `android.os.Parcel#readParcelableCreator`"
- errorLine1=" return from.readParcelableCreator(loader);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParceledListSlice.java"
- line="82"
- column="21"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.TrackData#mediaFormat`"
- errorLine1=" this.mediaFormat = mediaFormat;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="273"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.TrackData#drmInitData`"
- errorLine1=" this.drmInitData = drmInitData;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="274"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" this.timeMicros = timeMicros;"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="295"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" this.position = position;"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="296"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" return "[timeMicros=" + timeMicros + ", position=" + position + "]";"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="302"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" return "[timeMicros=" + timeMicros + ", position=" + position + "]";"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="302"
- column="37"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.SeekPoint`"
- errorLine1=" SeekPoint other = (SeekPoint) obj;"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="313"
- column="32"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" return timeMicros == other.timeMicros && position == other.position;"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
- column="54"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" return timeMicros == other.timeMicros && position == other.position;"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" return timeMicros == other.timeMicros && position == other.position;"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
- column="20"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" return timeMicros == other.timeMicros && position == other.position;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
- column="34"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" int result = (int) timeMicros;"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="319"
- column="32"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" result = 31 * result + (int) position;"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="320"
- column="42"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
- errorLine1=" public interface SeekableInputReader extends InputReader {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="352"
- column="50"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level 31 (current min is 29): `android.media.metrics.LogSessionId#LOG_SESSION_ID_NONE`"
- errorLine1=" @NonNull private LogSessionId mLogSessionId = LogSessionId.LOG_SESSION_ID_NONE;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1071"
- column="51"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Cast from `SeekableInputReader` to `InputReader` requires API level 30 (current min is 29)"
- errorLine1=" mExoDataReader.mInputReader = seekableInputReader;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1201"
- column="39"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" mPendingSeekPosition = seekPoint.position;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1287"
- column="36"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" mPendingSeekTimeMicros = seekPoint.timeMicros;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1288"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" mExtractor.seek(seekPoint.position, seekPoint.timeMicros);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1290"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" mExtractor.seek(seekPoint.position, seekPoint.timeMicros);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1290"
- column="49"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.DrmInitData.SchemeInitData#uuid`"
- errorLine1=" if (schemeInitData.uuid.equals(schemeUuid)) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1579"
- column="21"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
- errorLine1=" private static final class DataReaderAdapter implements InputReader {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1872"
- column="61"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
- errorLine1=" private static final class ParsableByteArrayAdapter implements InputReader {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1905"
- column="68"/>
- </issue>
-
-</issues>
diff --git a/apex/media/framework/updatable-media-proguard.flags b/apex/media/framework/updatable-media-proguard.flags
deleted file mode 100644
index 4e7d842..0000000
--- a/apex/media/framework/updatable-media-proguard.flags
+++ /dev/null
@@ -1,2 +0,0 @@
-# Keep all symbols in android.media.
--keep class android.media.* {*;}
diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp
deleted file mode 100644
index 271fc53..0000000
--- a/apex/media/service/Android.bp
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package {
- // 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"],
-}
-
-filegroup {
- name: "service-media-s-sources",
- srcs: [
- "java/**/*.java",
- ],
- path: "java",
- visibility: ["//visibility:private"],
-}
-
-java_sdk_library {
- name: "service-media-s",
- permitted_packages: [
- "com.android.server.media",
- ],
- defaults: ["framework-system-server-module-defaults"],
- srcs: [
- ":service-media-s-sources",
- ],
- libs: [
- "updatable-media",
- ],
- sdk_version: "system_server_current",
- min_sdk_version: "29", // TODO: We may need to bump this at some point.
- apex_available: [
- "com.android.media",
- ],
-}
diff --git a/apex/media/service/api/current.txt b/apex/media/service/api/current.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/api/removed.txt b/apex/media/service/api/removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/api/system-server-current.txt b/apex/media/service/api/system-server-current.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/system-server-current.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/api/system-server-removed.txt b/apex/media/service/api/system-server-removed.txt
deleted file mode 100644
index d802177..0000000
--- a/apex/media/service/api/system-server-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
deleted file mode 100644
index ed31aa3..0000000
--- a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.media;
-
-import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
-import static android.os.UserHandle.ALL;
-import static android.os.UserHandle.getUserHandleForUid;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.media.IMediaCommunicationService;
-import android.media.IMediaCommunicationServiceCallback;
-import android.media.MediaController2;
-import android.media.MediaParceledListSlice;
-import android.media.Session2CommandGroup;
-import android.media.Session2Token;
-import android.os.Binder;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.SystemService;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.stream.Collectors;
-
-/**
- * A system service that manages {@link android.media.MediaSession2} creations
- * and their ongoing media playback state.
- * @hide
- */
-public class MediaCommunicationService extends SystemService {
- private static final String TAG = "MediaCommunicationService";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- final Context mContext;
-
- final Object mLock = new Object();
- final Handler mHandler = new Handler(Looper.getMainLooper());
-
- @GuardedBy("mLock")
- private final SparseIntArray mFullUserIds = new SparseIntArray();
- @GuardedBy("mLock")
- private final SparseArray<FullUserRecord> mUserRecords = new SparseArray<>();
-
- final Executor mRecordExecutor = Executors.newSingleThreadExecutor();
- @GuardedBy("mLock")
- final List<CallbackRecord> mCallbackRecords = new ArrayList<>();
- final NotificationManager mNotificationManager;
-
- public MediaCommunicationService(Context context) {
- super(context);
- mContext = context;
- mNotificationManager = context.getSystemService(NotificationManager.class);
- }
-
- @Override
- public void onStart() {
- publishBinderService(Context.MEDIA_COMMUNICATION_SERVICE, new Stub());
- updateUser();
- }
-
- @Override
- public void onUserStarting(@NonNull TargetUser user) {
- if (DEBUG) Log.d(TAG, "onUserStarting: " + user);
- updateUser();
- }
-
- @Override
- public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
- if (DEBUG) Log.d(TAG, "onUserSwitching: " + to);
- updateUser();
- }
-
- @Override
- public void onUserStopped(@NonNull TargetUser targetUser) {
- int userId = targetUser.getUserHandle().getIdentifier();
-
- if (DEBUG) Log.d(TAG, "onUserStopped: " + userId);
- synchronized (mLock) {
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user != null) {
- if (user.getFullUserId() == userId) {
- user.destroyAllSessions();
- mUserRecords.remove(userId);
- } else {
- user.destroySessionsForUser(userId);
- }
- }
- }
- updateUser();
- }
-
- @Nullable
- CallbackRecord findCallbackRecordLocked(@Nullable IMediaCommunicationServiceCallback callback) {
- if (callback == null) {
- return null;
- }
- for (CallbackRecord record : mCallbackRecords) {
- if (Objects.equals(callback.asBinder(), record.mCallback.asBinder())) {
- return record;
- }
- }
- return null;
- }
-
- List<Session2Token> getSession2TokensLocked(int userId) {
- List<Session2Token> list = new ArrayList<>();
- if (userId == ALL.getIdentifier()) {
- int size = mUserRecords.size();
- for (int i = 0; i < size; i++) {
- list.addAll(mUserRecords.valueAt(i).getAllSession2Tokens());
- }
- } else {
- FullUserRecord user = getFullUserRecordLocked(userId);
- if (user != null) {
- list.addAll(user.getSession2Tokens(userId));
- }
- }
- return list;
- }
-
- private FullUserRecord getFullUserRecordLocked(int userId) {
- int fullUserId = mFullUserIds.get(userId, -1);
- if (fullUserId < 0) {
- return null;
- }
- return mUserRecords.get(fullUserId);
- }
-
- private boolean hasMediaControlPermission(int pid, int uid) {
- // Check if it's system server or has MEDIA_CONTENT_CONTROL.
- // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
- // check here.
- if (uid == Process.SYSTEM_UID || mContext.checkPermission(
- android.Manifest.permission.MEDIA_CONTENT_CONTROL, pid, uid)
- == PackageManager.PERMISSION_GRANTED) {
- return true;
- } else if (DEBUG) {
- Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
- }
- return false;
- }
-
- private void updateUser() {
- UserManager manager = mContext.getSystemService(UserManager.class);
- List<UserHandle> allUsers = manager.getUserHandles(/*excludeDying=*/false);
-
- synchronized (mLock) {
- mFullUserIds.clear();
- if (allUsers != null) {
- for (UserHandle user : allUsers) {
- UserHandle parent = manager.getProfileParent(user);
- if (parent != null) {
- mFullUserIds.put(user.getIdentifier(), parent.getIdentifier());
- } else {
- mFullUserIds.put(user.getIdentifier(), user.getIdentifier());
- if (mUserRecords.get(user.getIdentifier()) == null) {
- mUserRecords.put(user.getIdentifier(),
- new FullUserRecord(user.getIdentifier()));
- }
- }
- }
- }
- // Ensure that the current full user exists.
- int currentFullUserId = ActivityManager.getCurrentUser();
- FullUserRecord currentFullUserRecord = mUserRecords.get(currentFullUserId);
- if (currentFullUserRecord == null) {
- Log.w(TAG, "Cannot find FullUserInfo for the current user " + currentFullUserId);
- currentFullUserRecord = new FullUserRecord(currentFullUserId);
- mUserRecords.put(currentFullUserId, currentFullUserRecord);
- }
- mFullUserIds.put(currentFullUserId, currentFullUserId);
- }
- }
-
- void dispatchSession2Created(Session2Token token) {
- synchronized (mLock) {
- for (CallbackRecord record : mCallbackRecords) {
- if (record.mUserId != ALL.getIdentifier()
- && record.mUserId != getUserHandleForUid(token.getUid()).getIdentifier()) {
- continue;
- }
- try {
- record.mCallback.onSession2Created(token);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to notify session2 token created " + record);
- }
- }
- }
- }
-
- void dispatchSession2Changed(int userId) {
- MediaParceledListSlice<Session2Token> allSession2Tokens;
- MediaParceledListSlice<Session2Token> userSession2Tokens;
-
- synchronized (mLock) {
- allSession2Tokens =
- new MediaParceledListSlice<>(getSession2TokensLocked(ALL.getIdentifier()));
- userSession2Tokens = new MediaParceledListSlice<>(getSession2TokensLocked(userId));
- }
- allSession2Tokens.setInlineCountLimit(1);
- userSession2Tokens.setInlineCountLimit(1);
-
- synchronized (mLock) {
- for (CallbackRecord record : mCallbackRecords) {
- if (record.mUserId == ALL.getIdentifier()) {
- try {
- record.mCallback.onSession2Changed(allSession2Tokens);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to notify session2 tokens changed " + record);
- }
- } else if (record.mUserId == userId) {
- try {
- record.mCallback.onSession2Changed(userSession2Tokens);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to notify session2 tokens changed " + record);
- }
- }
- }
- }
- }
-
- void onSessionDied(Session2Record session) {
- if (DEBUG) {
- Log.d(TAG, "Destroying " + session);
- }
- if (session.isClosed()) {
- Log.w(TAG, "Destroying already destroyed session. Ignoring.");
- return;
- }
-
- FullUserRecord user = session.getFullUser();
- if (user != null) {
- user.removeSession(session);
- }
- session.close();
- }
-
- private class Stub extends IMediaCommunicationService.Stub {
- @Override
- public void notifySession2Created(Session2Token sessionToken) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- try {
- if (DEBUG) {
- Log.d(TAG, "Session2 is created " + sessionToken);
- }
- if (uid != sessionToken.getUid()) {
- throw new SecurityException("Unexpected Session2Token's UID, expected=" + uid
- + " but actually=" + sessionToken.getUid());
- }
- FullUserRecord user;
- int userId = getUserHandleForUid(sessionToken.getUid()).getIdentifier();
- synchronized (mLock) {
- user = getFullUserRecordLocked(userId);
- }
- if (user == null) {
- Log.w(TAG, "notifySession2Created: Ignore session of an unknown user");
- return;
- }
- user.addSession(new Session2Record(MediaCommunicationService.this,
- user, sessionToken, mRecordExecutor));
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- /**
- * Returns if the controller's package is trusted (i.e. has either MEDIA_CONTENT_CONTROL
- * permission or an enabled notification listener)
- *
- * @param controllerPackageName package name of the controller app
- * @param controllerPid pid of the controller app
- * @param controllerUid uid of the controller app
- */
- @Override
- public boolean isTrusted(String controllerPackageName, int controllerPid,
- int controllerUid) {
- final int uid = Binder.getCallingUid();
- final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier();
- final long token = Binder.clearCallingIdentity();
- try {
- // Don't perform check between controllerPackageName and controllerUid.
- // When an (activity|service) runs on the another apps process by specifying
- // android:process in the AndroidManifest.xml, then PID and UID would have the
- // running process' information instead of the (activity|service) that has created
- // MediaController.
- // Note that we can use Context#getOpPackageName() instead of
- // Context#getPackageName() for getting package name that matches with the PID/UID,
- // but it doesn't tell which package has created the MediaController, so useless.
- return hasMediaControlPermission(controllerPid, controllerUid)
- || hasEnabledNotificationListener(
- userId, controllerPackageName, controllerUid);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public MediaParceledListSlice getSession2Tokens(int userId) {
- final int pid = Binder.getCallingPid();
- final int uid = Binder.getCallingUid();
- final long token = Binder.clearCallingIdentity();
-
- try {
- // Check that they can make calls on behalf of the user and get the final user id
- int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
- List<Session2Token> result;
- synchronized (mLock) {
- result = getSession2TokensLocked(resolvedUserId);
- }
- MediaParceledListSlice parceledListSlice = new MediaParceledListSlice<>(result);
- parceledListSlice.setInlineCountLimit(1);
- return parceledListSlice;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public void registerCallback(IMediaCommunicationServiceCallback callback,
- String packageName) throws RemoteException {
- Objects.requireNonNull(callback, "callback should not be null");
- Objects.requireNonNull(packageName, "packageName should not be null");
-
- synchronized (mLock) {
- if (findCallbackRecordLocked(callback) == null) {
-
- CallbackRecord record = new CallbackRecord(callback, packageName,
- Binder.getCallingUid(), Binder.getCallingPid());
- mCallbackRecords.add(record);
- try {
- callback.asBinder().linkToDeath(record, 0);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to register callback", e);
- mCallbackRecords.remove(record);
- }
- } else {
- Log.e(TAG, "registerCallback is called with already registered callback. "
- + "packageName=" + packageName);
- }
- }
- }
-
- @Override
- public void unregisterCallback(IMediaCommunicationServiceCallback callback)
- throws RemoteException {
- synchronized (mLock) {
- CallbackRecord existingRecord = findCallbackRecordLocked(callback);
- if (existingRecord != null) {
- mCallbackRecords.remove(existingRecord);
- callback.asBinder().unlinkToDeath(existingRecord, 0);
- } else {
- Log.e(TAG, "unregisterCallback is called with unregistered callback.");
- }
- }
- }
-
- private boolean hasEnabledNotificationListener(int callingUserId,
- String controllerPackageName, int controllerUid) {
- int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
- if (callingUserId != controllerUserId) {
- // Enabled notification listener only works within the same user.
- return false;
- }
-
- if (mNotificationManager.hasEnabledNotificationListener(controllerPackageName,
- UserHandle.getUserHandleForUid(controllerUid))) {
- return true;
- }
- if (DEBUG) {
- Log.d(TAG, controllerPackageName + " (uid=" + controllerUid
- + ") doesn't have an enabled notification listener");
- }
- return false;
- }
-
- // Handles incoming user by checking whether the caller has permission to access the
- // given user id's information or not. Permission is not necessary if the given user id is
- // equal to the caller's user id, but if not, the caller needs to have the
- // INTERACT_ACROSS_USERS_FULL permission. Otherwise, a security exception will be thrown.
- // The return value will be the given user id, unless the given user id is
- // UserHandle.CURRENT, which will return the ActivityManager.getCurrentUser() value instead.
- private int handleIncomingUser(int pid, int uid, int userId, String packageName) {
- int callingUserId = UserHandle.getUserHandleForUid(uid).getIdentifier();
- if (userId == callingUserId) {
- return userId;
- }
-
- boolean canInteractAcrossUsersFull = mContext.checkPermission(
- INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED;
- if (canInteractAcrossUsersFull) {
- if (userId == UserHandle.CURRENT.getIdentifier()) {
- return ActivityManager.getCurrentUser();
- }
- return userId;
- }
-
- throw new SecurityException("Permission denied while calling from " + packageName
- + " with user id: " + userId + "; Need to run as either the calling user id ("
- + callingUserId + "), or with " + INTERACT_ACROSS_USERS_FULL + " permission");
- }
- }
-
- final class CallbackRecord implements IBinder.DeathRecipient {
- private final IMediaCommunicationServiceCallback mCallback;
- private final String mPackageName;
- private final int mUid;
- private int mPid;
- private final int mUserId;
-
- CallbackRecord(IMediaCommunicationServiceCallback callback,
- String packageName, int uid, int pid) {
- mCallback = callback;
- mPackageName = packageName;
- mUid = uid;
- mPid = pid;
- mUserId = (mContext.checkPermission(
- INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED)
- ? ALL.getIdentifier() : UserHandle.getUserHandleForUid(mUid).getIdentifier();
- }
-
- @Override
- public String toString() {
- return "CallbackRecord[callback=" + mCallback + ", pkg=" + mPackageName
- + ", uid=" + mUid + ", pid=" + mPid + "]";
- }
-
- @Override
- public void binderDied() {
- synchronized (mLock) {
- mCallbackRecords.remove(this);
- }
- }
- }
-
- final class FullUserRecord {
- private final int mFullUserId;
- private final Object mUserLock = new Object();
- @GuardedBy("mUserLock")
- private final List<Session2Record> mSessionRecords = new ArrayList<>();
-
- FullUserRecord(int fullUserId) {
- mFullUserId = fullUserId;
- }
-
- public void addSession(Session2Record record) {
- synchronized (mUserLock) {
- mSessionRecords.add(record);
- }
- mHandler.post(() -> dispatchSession2Created(record.mSessionToken));
- mHandler.post(() -> dispatchSession2Changed(mFullUserId));
- }
-
- private void removeSession(Session2Record record) {
- synchronized (mUserLock) {
- mSessionRecords.remove(record);
- }
- mHandler.post(() -> dispatchSession2Changed(mFullUserId));
- //TODO: Handle if the removed session was the media button session.
- }
-
- public int getFullUserId() {
- return mFullUserId;
- }
-
- public List<Session2Token> getAllSession2Tokens() {
- synchronized (mUserLock) {
- return mSessionRecords.stream()
- .map(Session2Record::getSessionToken)
- .collect(Collectors.toList());
- }
- }
-
- public List<Session2Token> getSession2Tokens(int userId) {
- synchronized (mUserLock) {
- return mSessionRecords.stream()
- .filter(record -> record.getUserId() == userId)
- .map(Session2Record::getSessionToken)
- .collect(Collectors.toList());
- }
- }
-
- public void destroyAllSessions() {
- synchronized (mUserLock) {
- for (Session2Record session : mSessionRecords) {
- session.close();
- }
- mSessionRecords.clear();
- }
- mHandler.post(() -> dispatchSession2Changed(mFullUserId));
- }
-
- public void destroySessionsForUser(int userId) {
- boolean changed = false;
- synchronized (mUserLock) {
- for (int i = mSessionRecords.size() - 1; i >= 0; i--) {
- Session2Record session = mSessionRecords.get(i);
- if (session.getUserId() == userId) {
- mSessionRecords.remove(i);
- session.close();
- changed = true;
- }
- }
- }
- if (changed) {
- mHandler.post(() -> dispatchSession2Changed(mFullUserId));
- }
- }
- }
-
- static final class Session2Record {
- final Session2Token mSessionToken;
- final Object mSession2RecordLock = new Object();
- final WeakReference<MediaCommunicationService> mServiceRef;
- final WeakReference<FullUserRecord> mFullUserRef;
- @GuardedBy("mSession2RecordLock")
- private final MediaController2 mController;
-
- @GuardedBy("mSession2RecordLock")
- boolean mIsConnected;
- @GuardedBy("mSession2RecordLock")
- private boolean mIsClosed;
-
- Session2Record(MediaCommunicationService service, FullUserRecord fullUser,
- Session2Token token, Executor controllerExecutor) {
- mServiceRef = new WeakReference<>(service);
- mFullUserRef = new WeakReference<>(fullUser);
- mSessionToken = token;
- mController = new MediaController2.Builder(service.getContext(), token)
- .setControllerCallback(controllerExecutor, new Controller2Callback())
- .build();
- }
-
- public int getUserId() {
- return UserHandle.getUserHandleForUid(mSessionToken.getUid()).getIdentifier();
- }
-
- public FullUserRecord getFullUser() {
- return mFullUserRef.get();
- }
-
- public boolean isClosed() {
- synchronized (mSession2RecordLock) {
- return mIsClosed;
- }
- }
-
- public void close() {
- synchronized (mSession2RecordLock) {
- mIsClosed = true;
- mController.close();
- }
- }
-
- public Session2Token getSessionToken() {
- return mSessionToken;
- }
-
- private class Controller2Callback extends MediaController2.ControllerCallback {
- @Override
- public void onConnected(MediaController2 controller,
- Session2CommandGroup allowedCommands) {
- if (DEBUG) {
- Log.d(TAG, "connected to " + mSessionToken + ", allowed=" + allowedCommands);
- }
- synchronized (mSession2RecordLock) {
- mIsConnected = true;
- }
- }
-
- @Override
- public void onDisconnected(MediaController2 controller) {
- if (DEBUG) {
- Log.d(TAG, "disconnected from " + mSessionToken);
- }
- synchronized (mSession2RecordLock) {
- mIsConnected = false;
- }
- MediaCommunicationService service = mServiceRef.get();
- if (service != null) {
- service.onSessionDied(Session2Record.this);
- }
- }
- }
- }
-}
diff --git a/api/Android.bp b/api/Android.bp
index 15356bd..69d602a 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -112,7 +112,7 @@
"framework-appsearch",
"framework-bluetooth",
"framework-connectivity",
- "framework-connectivity-tiramisu",
+ "framework-connectivity-t",
"framework-graphics",
"framework-media",
"framework-mediaprovider",
@@ -178,8 +178,10 @@
cmd: metalava_cmd +
"--check-compatibility:api:released $(location :android.api.module-lib.latest) " +
// Note: having "public" be the base of module-lib is not perfect -- it should
- // ideally be a merged public+system), but this will help when migrating from
- // MODULE_LIBS -> public.
+ // ideally be a merged public+system (which metalava is not currently able to generate).
+ // This "base" will help when migrating from MODULE_LIBS -> public, but not when
+ // migrating from MODULE_LIBS -> system (where it needs to instead be listed as
+ // an incompatibility).
"--check-compatibility:base $(location :frameworks-base-api-current.txt) " +
"--baseline:compatibility:released $(location :android-incompatibilities.api.module-lib.latest) " +
"--update-baseline:compatibility:released $(genDir)/updated-baseline.txt " +
diff --git a/api/OWNERS b/api/OWNERS
index a027270..4d8ed03 100644
--- a/api/OWNERS
+++ b/api/OWNERS
@@ -4,3 +4,6 @@
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 17649e8..5e5f60e 100644
--- a/api/api.go
+++ b/api/api.go
@@ -27,6 +27,7 @@
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
@@ -199,9 +200,28 @@
ctx.CreateModule(java.LibraryFactory, &props)
}
-func createMergedModuleLibStubs(ctx android.LoadHookContext, modules []string) {
+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")
@@ -269,7 +289,8 @@
createMergedPublicStubs(ctx, bootclasspath)
createMergedSystemStubs(ctx, bootclasspath)
- createMergedModuleLibStubs(ctx, bootclasspath)
+ createMergedFrameworkModuleLibStubs(ctx, bootclasspath)
+ createMergedFrameworkImpl(ctx, bootclasspath)
createMergedAnnotations(ctx, bootclasspath)
diff --git a/boot/hiddenapi/hiddenapi-max-target-o.txt b/boot/hiddenapi/hiddenapi-max-target-o.txt
index 9153426..e346ebf 100644
--- a/boot/hiddenapi/hiddenapi-max-target-o.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-o.txt
@@ -9315,78 +9315,6 @@
Landroid/app/usage/IUsageStatsManager;->setAppStandbyBuckets(Landroid/content/pm/ParceledListSlice;I)V
Landroid/app/usage/IUsageStatsManager;->unregisterAppUsageObserver(ILjava/lang/String;)V
Landroid/app/usage/IUsageStatsManager;->whitelistAppTemporarily(Ljava/lang/String;JI)V
-Landroid/app/usage/NetworkStats$Bucket;->convertDefaultNetworkStatus(I)I
-Landroid/app/usage/NetworkStats$Bucket;->convertMetered(I)I
-Landroid/app/usage/NetworkStats$Bucket;->convertRoaming(I)I
-Landroid/app/usage/NetworkStats$Bucket;->convertSet(I)I
-Landroid/app/usage/NetworkStats$Bucket;->convertState(I)I
-Landroid/app/usage/NetworkStats$Bucket;->convertTag(I)I
-Landroid/app/usage/NetworkStats$Bucket;->convertUid(I)I
-Landroid/app/usage/NetworkStats$Bucket;->mBeginTimeStamp:J
-Landroid/app/usage/NetworkStats$Bucket;->mDefaultNetworkStatus:I
-Landroid/app/usage/NetworkStats$Bucket;->mEndTimeStamp:J
-Landroid/app/usage/NetworkStats$Bucket;->mMetered:I
-Landroid/app/usage/NetworkStats$Bucket;->mRoaming:I
-Landroid/app/usage/NetworkStats$Bucket;->mRxBytes:J
-Landroid/app/usage/NetworkStats$Bucket;->mRxPackets:J
-Landroid/app/usage/NetworkStats$Bucket;->mState:I
-Landroid/app/usage/NetworkStats$Bucket;->mTag:I
-Landroid/app/usage/NetworkStats$Bucket;->mTxBytes:J
-Landroid/app/usage/NetworkStats$Bucket;->mTxPackets:J
-Landroid/app/usage/NetworkStats$Bucket;->mUid:I
-Landroid/app/usage/NetworkStats;-><init>(Landroid/content/Context;Landroid/net/NetworkTemplate;IJJLandroid/net/INetworkStatsService;)V
-Landroid/app/usage/NetworkStats;->fillBucketFromSummaryEntry(Landroid/app/usage/NetworkStats$Bucket;)V
-Landroid/app/usage/NetworkStats;->getDeviceSummaryForNetwork()Landroid/app/usage/NetworkStats$Bucket;
-Landroid/app/usage/NetworkStats;->getNextHistoryBucket(Landroid/app/usage/NetworkStats$Bucket;)Z
-Landroid/app/usage/NetworkStats;->getNextSummaryBucket(Landroid/app/usage/NetworkStats$Bucket;)Z
-Landroid/app/usage/NetworkStats;->getSummaryAggregate()Landroid/app/usage/NetworkStats$Bucket;
-Landroid/app/usage/NetworkStats;->getUid()I
-Landroid/app/usage/NetworkStats;->hasNextUid()Z
-Landroid/app/usage/NetworkStats;->isUidEnumeration()Z
-Landroid/app/usage/NetworkStats;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/app/usage/NetworkStats;->mEndTimeStamp:J
-Landroid/app/usage/NetworkStats;->mEnumerationIndex:I
-Landroid/app/usage/NetworkStats;->mHistory:Landroid/net/NetworkStatsHistory;
-Landroid/app/usage/NetworkStats;->mRecycledHistoryEntry:Landroid/net/NetworkStatsHistory$Entry;
-Landroid/app/usage/NetworkStats;->mRecycledSummaryEntry:Landroid/net/NetworkStats$Entry;
-Landroid/app/usage/NetworkStats;->mSession:Landroid/net/INetworkStatsSession;
-Landroid/app/usage/NetworkStats;->mStartTimeStamp:J
-Landroid/app/usage/NetworkStats;->mState:I
-Landroid/app/usage/NetworkStats;->mSummary:Landroid/net/NetworkStats;
-Landroid/app/usage/NetworkStats;->mTag:I
-Landroid/app/usage/NetworkStats;->mTemplate:Landroid/net/NetworkTemplate;
-Landroid/app/usage/NetworkStats;->mUidOrUidIndex:I
-Landroid/app/usage/NetworkStats;->mUids:[I
-Landroid/app/usage/NetworkStats;->setSingleUidTagState(III)V
-Landroid/app/usage/NetworkStats;->startHistoryEnumeration(III)V
-Landroid/app/usage/NetworkStats;->startSummaryEnumeration()V
-Landroid/app/usage/NetworkStats;->startUserUidEnumeration()V
-Landroid/app/usage/NetworkStats;->stepHistory()V
-Landroid/app/usage/NetworkStats;->stepUid()V
-Landroid/app/usage/NetworkStats;->TAG:Ljava/lang/String;
-Landroid/app/usage/NetworkStatsManager$CallbackHandler;-><init>(Landroid/os/Looper;ILjava/lang/String;Landroid/app/usage/NetworkStatsManager$UsageCallback;)V
-Landroid/app/usage/NetworkStatsManager$CallbackHandler;->getObject(Landroid/os/Message;Ljava/lang/String;)Ljava/lang/Object;
-Landroid/app/usage/NetworkStatsManager$CallbackHandler;->mCallback:Landroid/app/usage/NetworkStatsManager$UsageCallback;
-Landroid/app/usage/NetworkStatsManager$CallbackHandler;->mNetworkType:I
-Landroid/app/usage/NetworkStatsManager$CallbackHandler;->mSubscriberId:Ljava/lang/String;
-Landroid/app/usage/NetworkStatsManager$UsageCallback;->request:Landroid/net/DataUsageRequest;
-Landroid/app/usage/NetworkStatsManager;-><init>(Landroid/content/Context;Landroid/net/INetworkStatsService;)V
-Landroid/app/usage/NetworkStatsManager;->CALLBACK_LIMIT_REACHED:I
-Landroid/app/usage/NetworkStatsManager;->CALLBACK_RELEASED:I
-Landroid/app/usage/NetworkStatsManager;->createTemplate(ILjava/lang/String;)Landroid/net/NetworkTemplate;
-Landroid/app/usage/NetworkStatsManager;->DBG:Z
-Landroid/app/usage/NetworkStatsManager;->FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN:I
-Landroid/app/usage/NetworkStatsManager;->FLAG_POLL_FORCE:I
-Landroid/app/usage/NetworkStatsManager;->FLAG_POLL_ON_OPEN:I
-Landroid/app/usage/NetworkStatsManager;->mContext:Landroid/content/Context;
-Landroid/app/usage/NetworkStatsManager;->mFlags:I
-Landroid/app/usage/NetworkStatsManager;->MIN_THRESHOLD_BYTES:J
-Landroid/app/usage/NetworkStatsManager;->mService:Landroid/net/INetworkStatsService;
-Landroid/app/usage/NetworkStatsManager;->querySummaryForDevice(Landroid/net/NetworkTemplate;JJ)Landroid/app/usage/NetworkStats$Bucket;
-Landroid/app/usage/NetworkStatsManager;->registerUsageCallback(Landroid/net/NetworkTemplate;IJLandroid/app/usage/NetworkStatsManager$UsageCallback;Landroid/os/Handler;)V
-Landroid/app/usage/NetworkStatsManager;->setAugmentWithSubscriptionPlan(Z)V
-Landroid/app/usage/NetworkStatsManager;->setPollOnOpen(Z)V
-Landroid/app/usage/NetworkStatsManager;->TAG:Ljava/lang/String;
Landroid/app/usage/StorageStats;-><init>()V
Landroid/app/usage/StorageStats;-><init>(Landroid/os/Parcel;)V
Landroid/app/usage/StorageStats;->cacheBytes:J
@@ -35338,13 +35266,6 @@
Landroid/net/Credentials;->gid:I
Landroid/net/Credentials;->pid:I
Landroid/net/Credentials;->uid:I
-Landroid/net/DataUsageRequest;-><init>(ILandroid/net/NetworkTemplate;J)V
-Landroid/net/DataUsageRequest;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/DataUsageRequest;->PARCELABLE_KEY:Ljava/lang/String;
-Landroid/net/DataUsageRequest;->requestId:I
-Landroid/net/DataUsageRequest;->REQUEST_ID_UNSET:I
-Landroid/net/DataUsageRequest;->template:Landroid/net/NetworkTemplate;
-Landroid/net/DataUsageRequest;->thresholdInBytes:J
Landroid/net/DhcpResults;->addDns(Ljava/lang/String;)Z
Landroid/net/DhcpResults;->clear()V
Landroid/net/DhcpResults;->CREATOR:Landroid/os/Parcelable$Creator;
@@ -35446,51 +35367,6 @@
Landroid/net/IIpConnectivityMetrics;->addNetdEventCallback(ILandroid/net/INetdEventCallback;)Z
Landroid/net/IIpConnectivityMetrics;->logEvent(Landroid/net/ConnectivityMetricsEvent;)I
Landroid/net/IIpConnectivityMetrics;->removeNetdEventCallback(I)Z
-Landroid/net/IIpSecService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/IIpSecService$Stub$Proxy;->addAddressToTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->allocateSecurityParameterIndex(Ljava/lang/String;ILandroid/os/IBinder;)Landroid/net/IpSecSpiResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->applyTransportModeTransform(Landroid/os/ParcelFileDescriptor;II)V
-Landroid/net/IIpSecService$Stub$Proxy;->applyTunnelModeTransform(IIILjava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->closeUdpEncapsulationSocket(I)V
-Landroid/net/IIpSecService$Stub$Proxy;->createTransform(Landroid/net/IpSecConfig;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTransformResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->createTunnelInterface(Ljava/lang/String;Ljava/lang/String;Landroid/net/Network;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTunnelInterfaceResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->deleteTransform(I)V
-Landroid/net/IIpSecService$Stub$Proxy;->deleteTunnelInterface(ILjava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/IIpSecService$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/IIpSecService$Stub$Proxy;->openUdpEncapsulationSocket(ILandroid/os/IBinder;)Landroid/net/IpSecUdpEncapResponse;
-Landroid/net/IIpSecService$Stub$Proxy;->releaseSecurityParameterIndex(I)V
-Landroid/net/IIpSecService$Stub$Proxy;->removeAddressFromTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService$Stub$Proxy;->removeTransportModeTransforms(Landroid/os/ParcelFileDescriptor;)V
-Landroid/net/IIpSecService$Stub;-><init>()V
-Landroid/net/IIpSecService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/IIpSecService;
-Landroid/net/IIpSecService$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/IIpSecService$Stub;->TRANSACTION_addAddressToTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_allocateSecurityParameterIndex:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_applyTransportModeTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_applyTunnelModeTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_closeUdpEncapsulationSocket:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_createTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_createTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_deleteTransform:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_deleteTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_openUdpEncapsulationSocket:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_releaseSecurityParameterIndex:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_removeAddressFromTunnelInterface:I
-Landroid/net/IIpSecService$Stub;->TRANSACTION_removeTransportModeTransforms:I
-Landroid/net/IIpSecService;->addAddressToTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService;->allocateSecurityParameterIndex(Ljava/lang/String;ILandroid/os/IBinder;)Landroid/net/IpSecSpiResponse;
-Landroid/net/IIpSecService;->applyTransportModeTransform(Landroid/os/ParcelFileDescriptor;II)V
-Landroid/net/IIpSecService;->applyTunnelModeTransform(IIILjava/lang/String;)V
-Landroid/net/IIpSecService;->closeUdpEncapsulationSocket(I)V
-Landroid/net/IIpSecService;->createTransform(Landroid/net/IpSecConfig;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTransformResponse;
-Landroid/net/IIpSecService;->createTunnelInterface(Ljava/lang/String;Ljava/lang/String;Landroid/net/Network;Landroid/os/IBinder;Ljava/lang/String;)Landroid/net/IpSecTunnelInterfaceResponse;
-Landroid/net/IIpSecService;->deleteTransform(I)V
-Landroid/net/IIpSecService;->deleteTunnelInterface(ILjava/lang/String;)V
-Landroid/net/IIpSecService;->openUdpEncapsulationSocket(ILandroid/os/IBinder;)Landroid/net/IpSecUdpEncapResponse;
-Landroid/net/IIpSecService;->releaseSecurityParameterIndex(I)V
-Landroid/net/IIpSecService;->removeAddressFromTunnelInterface(ILandroid/net/LinkAddress;Ljava/lang/String;)V
-Landroid/net/IIpSecService;->removeTransportModeTransforms(Landroid/os/ParcelFileDescriptor;)V
Landroid/net/INetd$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/net/INetd$Stub$Proxy;->addVirtualTunnelInterface(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V
Landroid/net/INetd$Stub$Proxy;->bandwidthEnableDataSaver(Z)Z
@@ -35838,68 +35714,6 @@
Landroid/net/INetworkScoreService;->setActiveScorer(Ljava/lang/String;)Z
Landroid/net/INetworkScoreService;->unregisterNetworkScoreCache(ILandroid/net/INetworkScoreCache;)V
Landroid/net/INetworkScoreService;->updateScores([Landroid/net/ScoredNetwork;)Z
-Landroid/net/INetworkStatsService$Stub$Proxy;->forceUpdate()V
-Landroid/net/INetworkStatsService$Stub$Proxy;->forceUpdateIfaces([Landroid/net/Network;)V
-Landroid/net/INetworkStatsService$Stub$Proxy;->getDataLayerSnapshotForUid(I)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsService$Stub$Proxy;->getDetailedUidStats([Ljava/lang/String;)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsService$Stub$Proxy;->getIfaceStats(Ljava/lang/String;I)J
-Landroid/net/INetworkStatsService$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/INetworkStatsService$Stub$Proxy;->getTotalStats(I)J
-Landroid/net/INetworkStatsService$Stub$Proxy;->getUidStats(II)J
-Landroid/net/INetworkStatsService$Stub$Proxy;->incrementOperationCount(III)V
-Landroid/net/INetworkStatsService$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/INetworkStatsService$Stub$Proxy;->openSession()Landroid/net/INetworkStatsSession;
-Landroid/net/INetworkStatsService$Stub$Proxy;->openSessionForUsageStats(ILjava/lang/String;)Landroid/net/INetworkStatsSession;
-Landroid/net/INetworkStatsService$Stub$Proxy;->registerUsageCallback(Ljava/lang/String;Landroid/net/DataUsageRequest;Landroid/os/Messenger;Landroid/os/IBinder;)Landroid/net/DataUsageRequest;
-Landroid/net/INetworkStatsService$Stub$Proxy;->unregisterUsageRequest(Landroid/net/DataUsageRequest;)V
-Landroid/net/INetworkStatsService$Stub;-><init>()V
-Landroid/net/INetworkStatsService$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_forceUpdate:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_forceUpdateIfaces:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_getDataLayerSnapshotForUid:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_getDetailedUidStats:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_getIfaceStats:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_getMobileIfaces:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_getTotalStats:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_getUidStats:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_incrementOperationCount:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_openSession:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_openSessionForUsageStats:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_registerUsageCallback:I
-Landroid/net/INetworkStatsService$Stub;->TRANSACTION_unregisterUsageRequest:I
-Landroid/net/INetworkStatsService;->forceUpdateIfaces([Landroid/net/Network;)V
-Landroid/net/INetworkStatsService;->getDetailedUidStats([Ljava/lang/String;)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsService;->getIfaceStats(Ljava/lang/String;I)J
-Landroid/net/INetworkStatsService;->getTotalStats(I)J
-Landroid/net/INetworkStatsService;->getUidStats(II)J
-Landroid/net/INetworkStatsService;->incrementOperationCount(III)V
-Landroid/net/INetworkStatsService;->registerUsageCallback(Ljava/lang/String;Landroid/net/DataUsageRequest;Landroid/os/Messenger;Landroid/os/IBinder;)Landroid/net/DataUsageRequest;
-Landroid/net/INetworkStatsService;->unregisterUsageRequest(Landroid/net/DataUsageRequest;)V
-Landroid/net/INetworkStatsSession$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/INetworkStatsSession$Stub$Proxy;->close()V
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getDeviceSummaryForNetwork(Landroid/net/NetworkTemplate;JJ)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getHistoryForNetwork(Landroid/net/NetworkTemplate;I)Landroid/net/NetworkStatsHistory;
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getHistoryForUid(Landroid/net/NetworkTemplate;IIII)Landroid/net/NetworkStatsHistory;
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getHistoryIntervalForUid(Landroid/net/NetworkTemplate;IIIIJJ)Landroid/net/NetworkStatsHistory;
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getRelevantUids()[I
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getSummaryForAllUid(Landroid/net/NetworkTemplate;JJZ)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsSession$Stub$Proxy;->getSummaryForNetwork(Landroid/net/NetworkTemplate;JJ)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsSession$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/INetworkStatsSession$Stub;-><init>()V
-Landroid/net/INetworkStatsSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsSession;
-Landroid/net/INetworkStatsSession$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_close:I
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_getDeviceSummaryForNetwork:I
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_getHistoryForNetwork:I
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_getHistoryForUid:I
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_getHistoryIntervalForUid:I
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_getRelevantUids:I
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_getSummaryForAllUid:I
-Landroid/net/INetworkStatsSession$Stub;->TRANSACTION_getSummaryForNetwork:I
-Landroid/net/INetworkStatsSession;->getDeviceSummaryForNetwork(Landroid/net/NetworkTemplate;JJ)Landroid/net/NetworkStats;
-Landroid/net/INetworkStatsSession;->getHistoryIntervalForUid(Landroid/net/NetworkTemplate;IIIIJJ)Landroid/net/NetworkStatsHistory;
-Landroid/net/INetworkStatsSession;->getRelevantUids()[I
Landroid/net/InterfaceConfiguration;->CREATOR:Landroid/os/Parcelable$Creator;
Landroid/net/InterfaceConfiguration;->FLAG_DOWN:Ljava/lang/String;
Landroid/net/InterfaceConfiguration;->FLAG_UP:Ljava/lang/String;
@@ -35914,174 +35728,6 @@
Landroid/net/InterfaceConfiguration;->mHwAddr:Ljava/lang/String;
Landroid/net/InterfaceConfiguration;->setHardwareAddress(Ljava/lang/String;)V
Landroid/net/InterfaceConfiguration;->validateFlag(Ljava/lang/String;)V
-Landroid/net/IpSecAlgorithm;->checkValidOrThrow(Ljava/lang/String;II)V
-Landroid/net/IpSecAlgorithm;->CRYPT_NULL:Ljava/lang/String;
-Landroid/net/IpSecAlgorithm;->equals(Landroid/net/IpSecAlgorithm;Landroid/net/IpSecAlgorithm;)Z
-Landroid/net/IpSecAlgorithm;->isAead()Z
-Landroid/net/IpSecAlgorithm;->isAuthentication()Z
-Landroid/net/IpSecAlgorithm;->isEncryption()Z
-Landroid/net/IpSecAlgorithm;->isUnsafeBuild()Z
-Landroid/net/IpSecAlgorithm;->mKey:[B
-Landroid/net/IpSecAlgorithm;->mName:Ljava/lang/String;
-Landroid/net/IpSecAlgorithm;->mTruncLenBits:I
-Landroid/net/IpSecAlgorithm;->TAG:Ljava/lang/String;
-Landroid/net/IpSecConfig;-><init>()V
-Landroid/net/IpSecConfig;-><init>(Landroid/net/IpSecConfig;)V
-Landroid/net/IpSecConfig;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecConfig;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecConfig;->equals(Landroid/net/IpSecConfig;Landroid/net/IpSecConfig;)Z
-Landroid/net/IpSecConfig;->getAuthenticatedEncryption()Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->getAuthentication()Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->getDestinationAddress()Ljava/lang/String;
-Landroid/net/IpSecConfig;->getEncapRemotePort()I
-Landroid/net/IpSecConfig;->getEncapSocketResourceId()I
-Landroid/net/IpSecConfig;->getEncapType()I
-Landroid/net/IpSecConfig;->getEncryption()Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->getMarkMask()I
-Landroid/net/IpSecConfig;->getMarkValue()I
-Landroid/net/IpSecConfig;->getMode()I
-Landroid/net/IpSecConfig;->getNattKeepaliveInterval()I
-Landroid/net/IpSecConfig;->getNetwork()Landroid/net/Network;
-Landroid/net/IpSecConfig;->getSourceAddress()Ljava/lang/String;
-Landroid/net/IpSecConfig;->getSpiResourceId()I
-Landroid/net/IpSecConfig;->mAuthenticatedEncryption:Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->mAuthentication:Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->mDestinationAddress:Ljava/lang/String;
-Landroid/net/IpSecConfig;->mEncapRemotePort:I
-Landroid/net/IpSecConfig;->mEncapSocketResourceId:I
-Landroid/net/IpSecConfig;->mEncapType:I
-Landroid/net/IpSecConfig;->mEncryption:Landroid/net/IpSecAlgorithm;
-Landroid/net/IpSecConfig;->mMarkMask:I
-Landroid/net/IpSecConfig;->mMarkValue:I
-Landroid/net/IpSecConfig;->mMode:I
-Landroid/net/IpSecConfig;->mNattKeepaliveInterval:I
-Landroid/net/IpSecConfig;->mNetwork:Landroid/net/Network;
-Landroid/net/IpSecConfig;->mSourceAddress:Ljava/lang/String;
-Landroid/net/IpSecConfig;->mSpiResourceId:I
-Landroid/net/IpSecConfig;->setAuthenticatedEncryption(Landroid/net/IpSecAlgorithm;)V
-Landroid/net/IpSecConfig;->setAuthentication(Landroid/net/IpSecAlgorithm;)V
-Landroid/net/IpSecConfig;->setDestinationAddress(Ljava/lang/String;)V
-Landroid/net/IpSecConfig;->setEncapRemotePort(I)V
-Landroid/net/IpSecConfig;->setEncapSocketResourceId(I)V
-Landroid/net/IpSecConfig;->setEncapType(I)V
-Landroid/net/IpSecConfig;->setEncryption(Landroid/net/IpSecAlgorithm;)V
-Landroid/net/IpSecConfig;->setMarkMask(I)V
-Landroid/net/IpSecConfig;->setMarkValue(I)V
-Landroid/net/IpSecConfig;->setMode(I)V
-Landroid/net/IpSecConfig;->setNattKeepaliveInterval(I)V
-Landroid/net/IpSecConfig;->setNetwork(Landroid/net/Network;)V
-Landroid/net/IpSecConfig;->setSourceAddress(Ljava/lang/String;)V
-Landroid/net/IpSecConfig;->setSpiResourceId(I)V
-Landroid/net/IpSecConfig;->TAG:Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;-><init>(Landroid/content/Context;Landroid/net/IIpSecService;Ljava/net/InetAddress;Ljava/net/InetAddress;Landroid/net/Network;)V
-Landroid/net/IpSecManager$IpSecTunnelInterface;->addAddress(Ljava/net/InetAddress;I)V
-Landroid/net/IpSecManager$IpSecTunnelInterface;->getInterfaceName()Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->getResourceId()I
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mInterfaceName:Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mLocalAddress:Ljava/net/InetAddress;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mOpPackageName:Ljava/lang/String;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mRemoteAddress:Ljava/net/InetAddress;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mResourceId:I
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->mUnderlyingNetwork:Landroid/net/Network;
-Landroid/net/IpSecManager$IpSecTunnelInterface;->removeAddress(Ljava/net/InetAddress;I)V
-Landroid/net/IpSecManager$ResourceUnavailableException;-><init>(Ljava/lang/String;)V
-Landroid/net/IpSecManager$SecurityParameterIndex;-><init>(Landroid/net/IIpSecService;Ljava/net/InetAddress;I)V
-Landroid/net/IpSecManager$SecurityParameterIndex;->getResourceId()I
-Landroid/net/IpSecManager$SecurityParameterIndex;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecManager$SecurityParameterIndex;->mDestinationAddress:Ljava/net/InetAddress;
-Landroid/net/IpSecManager$SecurityParameterIndex;->mResourceId:I
-Landroid/net/IpSecManager$SecurityParameterIndex;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager$SecurityParameterIndex;->mSpi:I
-Landroid/net/IpSecManager$SpiUnavailableException;-><init>(Ljava/lang/String;I)V
-Landroid/net/IpSecManager$SpiUnavailableException;->mSpi:I
-Landroid/net/IpSecManager$Status;->OK:I
-Landroid/net/IpSecManager$Status;->RESOURCE_UNAVAILABLE:I
-Landroid/net/IpSecManager$Status;->SPI_UNAVAILABLE:I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;-><init>(Landroid/net/IIpSecService;I)V
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->getResourceId()I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mPfd:Landroid/os/ParcelFileDescriptor;
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mPort:I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mResourceId:I
-Landroid/net/IpSecManager$UdpEncapsulationSocket;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager;-><init>(Landroid/content/Context;Landroid/net/IIpSecService;)V
-Landroid/net/IpSecManager;->applyTunnelModeTransform(Landroid/net/IpSecManager$IpSecTunnelInterface;ILandroid/net/IpSecTransform;)V
-Landroid/net/IpSecManager;->createIpSecTunnelInterface(Ljava/net/InetAddress;Ljava/net/InetAddress;Landroid/net/Network;)Landroid/net/IpSecManager$IpSecTunnelInterface;
-Landroid/net/IpSecManager;->INVALID_RESOURCE_ID:I
-Landroid/net/IpSecManager;->maybeHandleServiceSpecificException(Landroid/os/ServiceSpecificException;)V
-Landroid/net/IpSecManager;->mContext:Landroid/content/Context;
-Landroid/net/IpSecManager;->mService:Landroid/net/IIpSecService;
-Landroid/net/IpSecManager;->removeTunnelModeTransform(Landroid/net/Network;Landroid/net/IpSecTransform;)V
-Landroid/net/IpSecManager;->rethrowCheckedExceptionFromServiceSpecificException(Landroid/os/ServiceSpecificException;)Ljava/io/IOException;
-Landroid/net/IpSecManager;->rethrowUncheckedExceptionFromServiceSpecificException(Landroid/os/ServiceSpecificException;)Ljava/lang/RuntimeException;
-Landroid/net/IpSecManager;->TAG:Ljava/lang/String;
-Landroid/net/IpSecSpiResponse;-><init>(I)V
-Landroid/net/IpSecSpiResponse;-><init>(III)V
-Landroid/net/IpSecSpiResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecSpiResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecSpiResponse;->resourceId:I
-Landroid/net/IpSecSpiResponse;->spi:I
-Landroid/net/IpSecSpiResponse;->status:I
-Landroid/net/IpSecSpiResponse;->TAG:Ljava/lang/String;
-Landroid/net/IpSecTransform$Builder;->buildTunnelModeTransform(Ljava/net/InetAddress;Landroid/net/IpSecManager$SecurityParameterIndex;)Landroid/net/IpSecTransform;
-Landroid/net/IpSecTransform$Builder;->mConfig:Landroid/net/IpSecConfig;
-Landroid/net/IpSecTransform$Builder;->mContext:Landroid/content/Context;
-Landroid/net/IpSecTransform$NattKeepaliveCallback;-><init>()V
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_HARDWARE_ERROR:I
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_HARDWARE_UNSUPPORTED:I
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->ERROR_INVALID_NETWORK:I
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->onError(I)V
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->onStarted()V
-Landroid/net/IpSecTransform$NattKeepaliveCallback;->onStopped()V
-Landroid/net/IpSecTransform;-><init>(Landroid/content/Context;Landroid/net/IpSecConfig;)V
-Landroid/net/IpSecTransform;->activate()Landroid/net/IpSecTransform;
-Landroid/net/IpSecTransform;->checkResultStatus(I)V
-Landroid/net/IpSecTransform;->ENCAP_ESPINUDP:I
-Landroid/net/IpSecTransform;->ENCAP_ESPINUDP_NON_IKE:I
-Landroid/net/IpSecTransform;->ENCAP_NONE:I
-Landroid/net/IpSecTransform;->equals(Landroid/net/IpSecTransform;Landroid/net/IpSecTransform;)Z
-Landroid/net/IpSecTransform;->getConfig()Landroid/net/IpSecConfig;
-Landroid/net/IpSecTransform;->getIpSecService()Landroid/net/IIpSecService;
-Landroid/net/IpSecTransform;->getResourceId()I
-Landroid/net/IpSecTransform;->mCallbackHandler:Landroid/os/Handler;
-Landroid/net/IpSecTransform;->mCloseGuard:Ldalvik/system/CloseGuard;
-Landroid/net/IpSecTransform;->mConfig:Landroid/net/IpSecConfig;
-Landroid/net/IpSecTransform;->mContext:Landroid/content/Context;
-Landroid/net/IpSecTransform;->mKeepalive:Landroid/net/ConnectivityManager$PacketKeepalive;
-Landroid/net/IpSecTransform;->mKeepaliveCallback:Landroid/net/ConnectivityManager$PacketKeepaliveCallback;
-Landroid/net/IpSecTransform;->MODE_TRANSPORT:I
-Landroid/net/IpSecTransform;->MODE_TUNNEL:I
-Landroid/net/IpSecTransform;->mResourceId:I
-Landroid/net/IpSecTransform;->mUserKeepaliveCallback:Landroid/net/IpSecTransform$NattKeepaliveCallback;
-Landroid/net/IpSecTransform;->startNattKeepalive(Landroid/net/IpSecTransform$NattKeepaliveCallback;ILandroid/os/Handler;)V
-Landroid/net/IpSecTransform;->stopNattKeepalive()V
-Landroid/net/IpSecTransform;->TAG:Ljava/lang/String;
-Landroid/net/IpSecTransformResponse;-><init>(I)V
-Landroid/net/IpSecTransformResponse;-><init>(II)V
-Landroid/net/IpSecTransformResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecTransformResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecTransformResponse;->resourceId:I
-Landroid/net/IpSecTransformResponse;->status:I
-Landroid/net/IpSecTransformResponse;->TAG:Ljava/lang/String;
-Landroid/net/IpSecTunnelInterfaceResponse;-><init>(I)V
-Landroid/net/IpSecTunnelInterfaceResponse;-><init>(IILjava/lang/String;)V
-Landroid/net/IpSecTunnelInterfaceResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecTunnelInterfaceResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecTunnelInterfaceResponse;->interfaceName:Ljava/lang/String;
-Landroid/net/IpSecTunnelInterfaceResponse;->resourceId:I
-Landroid/net/IpSecTunnelInterfaceResponse;->status:I
-Landroid/net/IpSecTunnelInterfaceResponse;->TAG:Ljava/lang/String;
-Landroid/net/IpSecUdpEncapResponse;-><init>(I)V
-Landroid/net/IpSecUdpEncapResponse;-><init>(IIILjava/io/FileDescriptor;)V
-Landroid/net/IpSecUdpEncapResponse;-><init>(Landroid/os/Parcel;)V
-Landroid/net/IpSecUdpEncapResponse;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/IpSecUdpEncapResponse;->fileDescriptor:Landroid/os/ParcelFileDescriptor;
-Landroid/net/IpSecUdpEncapResponse;->port:I
-Landroid/net/IpSecUdpEncapResponse;->resourceId:I
-Landroid/net/IpSecUdpEncapResponse;->status:I
-Landroid/net/IpSecUdpEncapResponse;->TAG:Ljava/lang/String;
Landroid/net/ITetheringStatsProvider$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/net/ITetheringStatsProvider$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
Landroid/net/ITetheringStatsProvider$Stub$Proxy;->getTetherStats(I)Landroid/net/NetworkStats;
@@ -36742,41 +36388,6 @@
Landroid/net/StringNetworkSpecifier;-><init>(Ljava/lang/String;)V
Landroid/net/StringNetworkSpecifier;->CREATOR:Landroid/os/Parcelable$Creator;
Landroid/net/StringNetworkSpecifier;->satisfiedBy(Landroid/net/NetworkSpecifier;)Z
-Landroid/net/TrafficStats;->addIfSupported(J)J
-Landroid/net/TrafficStats;->closeQuietly(Landroid/net/INetworkStatsSession;)V
-Landroid/net/TrafficStats;->GB_IN_BYTES:J
-Landroid/net/TrafficStats;->getDataLayerSnapshotForUid(Landroid/content/Context;)Landroid/net/NetworkStats;
-Landroid/net/TrafficStats;->getRxPackets(Ljava/lang/String;)J
-Landroid/net/TrafficStats;->getTxPackets(Ljava/lang/String;)J
-Landroid/net/TrafficStats;->KB_IN_BYTES:J
-Landroid/net/TrafficStats;->LOOPBACK_IFACE:Ljava/lang/String;
-Landroid/net/TrafficStats;->MB_IN_BYTES:J
-Landroid/net/TrafficStats;->PB_IN_BYTES:J
-Landroid/net/TrafficStats;->sActiveProfilingStart:Landroid/net/NetworkStats;
-Landroid/net/TrafficStats;->sProfilingLock:Ljava/lang/Object;
-Landroid/net/TrafficStats;->sStatsService:Landroid/net/INetworkStatsService;
-Landroid/net/TrafficStats;->startDataProfiling(Landroid/content/Context;)V
-Landroid/net/TrafficStats;->stopDataProfiling(Landroid/content/Context;)Landroid/net/NetworkStats;
-Landroid/net/TrafficStats;->TAG_SYSTEM_APP:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_BACKUP:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_DHCP:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_DOWNLOAD:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_GPS:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_MEDIA:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_NEIGHBOR:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_NTP:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_PAC:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_PROBE:I
-Landroid/net/TrafficStats;->TAG_SYSTEM_RESTORE:I
-Landroid/net/TrafficStats;->TB_IN_BYTES:J
-Landroid/net/TrafficStats;->TYPE_RX_BYTES:I
-Landroid/net/TrafficStats;->TYPE_RX_PACKETS:I
-Landroid/net/TrafficStats;->TYPE_TCP_RX_PACKETS:I
-Landroid/net/TrafficStats;->TYPE_TCP_TX_PACKETS:I
-Landroid/net/TrafficStats;->TYPE_TX_BYTES:I
-Landroid/net/TrafficStats;->TYPE_TX_PACKETS:I
-Landroid/net/TrafficStats;->UID_REMOVED:I
-Landroid/net/TrafficStats;->UID_TETHERING:I
Landroid/net/Uri$AbstractHierarchicalUri;-><init>()V
Landroid/net/Uri$AbstractHierarchicalUri;->getUserInfoPart()Landroid/net/Uri$Part;
Landroid/net/Uri$AbstractHierarchicalUri;->host:Ljava/lang/String;
diff --git a/boot/hiddenapi/hiddenapi-unsupported.txt b/boot/hiddenapi/hiddenapi-unsupported.txt
index 002d42d..e47149b 100644
--- a/boot/hiddenapi/hiddenapi-unsupported.txt
+++ b/boot/hiddenapi/hiddenapi-unsupported.txt
@@ -170,9 +170,6 @@
Landroid/net/INetworkManagementEventObserver$Stub;-><init>()V
Landroid/net/INetworkPolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkPolicyManager;
Landroid/net/INetworkScoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkScoreService;
-Landroid/net/INetworkStatsService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/INetworkStatsService$Stub$Proxy;->getMobileIfaces()[Ljava/lang/String;
-Landroid/net/INetworkStatsService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/INetworkStatsService;
Landroid/os/IBatteryPropertiesRegistrar$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Landroid/os/IDeviceIdentifiersPolicyService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdentifiersPolicyService;
Landroid/os/IDeviceIdleController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/os/IDeviceIdleController;
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index c134822..c202f6f 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -39,6 +39,7 @@
"-modernize-pass-by-value",
"-modernize-replace-disallow-copy-and-assign-macro",
"-modernize-return-braced-init-list",
+ "-modernize-use-default-member-init",
"-modernize-use-equals-default",
"-modernize-use-nodiscard",
"-modernize-use-override",
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index a8d6489..1b2d905 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -39,11 +39,9 @@
#include "idmap2/Result.h"
#include "idmap2/SysTrace.h"
-using android::IPCThreadState;
using android::base::StringPrintf;
using android::binder::Status;
using android::idmap2::BinaryStreamVisitor;
-using android::idmap2::FabricatedOverlay;
using android::idmap2::FabricatedOverlayContainer;
using android::idmap2::Idmap;
using android::idmap2::IdmapHeader;
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 9c6402a..738b9cf 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -37,7 +37,6 @@
#include "idmap2/Idmap.h"
#include "idmap2/LogInfo.h"
-using android::Res_value;
using ::testing::NotNull;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index 5a1d808..32b3d13 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -29,8 +29,6 @@
#include "idmap2/LogInfo.h"
#include "idmap2/ResourceMapping.h"
-using android::Res_value;
-
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 {
diff --git a/core/api/current.txt b/core/api/current.txt
index a32a3a9..42407ea 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8339,62 +8339,6 @@
field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.ExternalStorageStats> CREATOR;
}
- public final class NetworkStats implements java.lang.AutoCloseable {
- method public void close();
- method public boolean getNextBucket(android.app.usage.NetworkStats.Bucket);
- method public boolean hasNextBucket();
- }
-
- public static class NetworkStats.Bucket {
- ctor public NetworkStats.Bucket();
- method public int getDefaultNetworkStatus();
- method public long getEndTimeStamp();
- method public int getMetered();
- method public int getRoaming();
- method public long getRxBytes();
- method public long getRxPackets();
- method public long getStartTimeStamp();
- method public int getState();
- method public int getTag();
- method public long getTxBytes();
- method public long getTxPackets();
- method public int getUid();
- field public static final int DEFAULT_NETWORK_ALL = -1; // 0xffffffff
- field public static final int DEFAULT_NETWORK_NO = 1; // 0x1
- field public static final int DEFAULT_NETWORK_YES = 2; // 0x2
- field public static final int METERED_ALL = -1; // 0xffffffff
- field public static final int METERED_NO = 1; // 0x1
- field public static final int METERED_YES = 2; // 0x2
- field public static final int ROAMING_ALL = -1; // 0xffffffff
- field public static final int ROAMING_NO = 1; // 0x1
- field public static final int ROAMING_YES = 2; // 0x2
- field public static final int STATE_ALL = -1; // 0xffffffff
- field public static final int STATE_DEFAULT = 1; // 0x1
- field public static final int STATE_FOREGROUND = 2; // 0x2
- field public static final int TAG_NONE = 0; // 0x0
- field public static final int UID_ALL = -1; // 0xffffffff
- field public static final int UID_REMOVED = -4; // 0xfffffffc
- field public static final int UID_TETHERING = -5; // 0xfffffffb
- }
-
- public class NetworkStatsManager {
- method @WorkerThread public android.app.usage.NetworkStats queryDetails(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUid(int, String, long, long, int) throws java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTag(int, String, long, long, int, int) throws java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(int, String, long, long, int, int, int) throws java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats querySummary(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForUser(int, String, long, long) throws android.os.RemoteException, java.lang.SecurityException;
- method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback);
- method public void registerUsageCallback(int, String, long, android.app.usage.NetworkStatsManager.UsageCallback, @Nullable android.os.Handler);
- method public void unregisterUsageCallback(android.app.usage.NetworkStatsManager.UsageCallback);
- }
-
- public abstract static class NetworkStatsManager.UsageCallback {
- ctor public NetworkStatsManager.UsageCallback();
- method public abstract void onThresholdReached(int, String);
- }
-
public final class StorageStats implements android.os.Parcelable {
method public int describeContents();
method public long getAppBytes();
@@ -19114,6 +19058,7 @@
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
@@ -25198,6 +25143,14 @@
method public int getUid();
}
+ public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
+ ctor public EthernetNetworkSpecifier(@NonNull String);
+ method public int describeContents();
+ method @Nullable public String getInterfaceName();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR;
+ }
+
public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
method public int getMaxMtu();
@@ -25223,79 +25176,11 @@
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 setLocalRoutesExcluded(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);
- }
-
- public final class IpSecAlgorithm implements android.os.Parcelable {
- ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[]);
- ctor public IpSecAlgorithm(@NonNull String, @NonNull byte[], int);
- method public int describeContents();
- method @NonNull public byte[] getKey();
- method @NonNull public String getName();
- method @NonNull public static java.util.Set<java.lang.String> getSupportedAlgorithms();
- method public int getTruncationLengthBits();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final String AUTH_AES_CMAC = "cmac(aes)";
- field public static final String AUTH_AES_XCBC = "xcbc(aes)";
- field public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
- field public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)";
- field public static final String AUTH_HMAC_MD5 = "hmac(md5)";
- field public static final String AUTH_HMAC_SHA1 = "hmac(sha1)";
- field public static final String AUTH_HMAC_SHA256 = "hmac(sha256)";
- field public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
- field public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
- field @NonNull public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR;
- field public static final String CRYPT_AES_CBC = "cbc(aes)";
- field public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))";
- }
-
- public final class IpSecManager {
- method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException;
- method @NonNull public android.net.IpSecManager.SecurityParameterIndex allocateSecurityParameterIndex(@NonNull java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
- method public void applyTransportModeTransform(@NonNull java.net.Socket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
- method public void applyTransportModeTransform(@NonNull java.net.DatagramSocket, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
- method public void applyTransportModeTransform(@NonNull java.io.FileDescriptor, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
- method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
- method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
- method public void removeTransportModeTransforms(@NonNull java.net.Socket) throws java.io.IOException;
- method public void removeTransportModeTransforms(@NonNull java.net.DatagramSocket) throws java.io.IOException;
- method public void removeTransportModeTransforms(@NonNull java.io.FileDescriptor) throws java.io.IOException;
- field public static final int DIRECTION_IN = 0; // 0x0
- field public static final int DIRECTION_OUT = 1; // 0x1
- }
-
- public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException {
- }
-
- public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable {
- method public void close();
- method public int getSpi();
- }
-
- public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException {
- method public int getSpi();
- }
-
- public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
- method public void close() throws java.io.IOException;
- method public java.io.FileDescriptor getFileDescriptor();
- method public int getPort();
- }
-
- public final class IpSecTransform implements java.lang.AutoCloseable {
- method public void close();
- }
-
- public static class IpSecTransform.Builder {
- ctor public IpSecTransform.Builder(@NonNull android.content.Context);
- method @NonNull public android.net.IpSecTransform buildTransportModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
- method @NonNull public android.net.IpSecTransform.Builder setAuthenticatedEncryption(@NonNull android.net.IpSecAlgorithm);
- method @NonNull public android.net.IpSecTransform.Builder setAuthentication(@NonNull android.net.IpSecAlgorithm);
- method @NonNull public android.net.IpSecTransform.Builder setEncryption(@NonNull android.net.IpSecAlgorithm);
- method @NonNull public android.net.IpSecTransform.Builder setIpv4Encapsulation(@NonNull android.net.IpSecManager.UdpEncapsulationSocket, int);
+ method @NonNull public android.net.Ikev2VpnProfile.Builder setRequiresInternetValidation(boolean);
}
public class LocalServerSocket implements java.io.Closeable {
@@ -25369,9 +25254,10 @@
}
public abstract class PlatformVpnProfile {
- method public final boolean getExcludeLocalRoutes();
+ method public final boolean areLocalRoutesExcluded();
method public final int getType();
method @NonNull public final String getTypeString();
+ method public final boolean isInternetValidationRequired();
field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7
field public static final int TYPE_IKEV2_IPSEC_RSA = 8; // 0x8
field public static final int TYPE_IKEV2_IPSEC_USER_PASS = 6; // 0x6
@@ -25424,50 +25310,6 @@
method @NonNull public android.net.TelephonyNetworkSpecifier.Builder setSubscriptionId(int);
}
- public class TrafficStats {
- ctor public TrafficStats();
- method public static void clearThreadStatsTag();
- method public static void clearThreadStatsUid();
- method public static int getAndSetThreadStatsTag(int);
- method public static long getMobileRxBytes();
- method public static long getMobileRxPackets();
- method public static long getMobileTxBytes();
- method public static long getMobileTxPackets();
- method public static long getRxBytes(@NonNull String);
- method public static long getRxPackets(@NonNull String);
- method public static int getThreadStatsTag();
- method public static int getThreadStatsUid();
- method public static long getTotalRxBytes();
- method public static long getTotalRxPackets();
- method public static long getTotalTxBytes();
- method public static long getTotalTxPackets();
- method public static long getTxBytes(@NonNull String);
- method public static long getTxPackets(@NonNull String);
- method public static long getUidRxBytes(int);
- method public static long getUidRxPackets(int);
- method @Deprecated public static long getUidTcpRxBytes(int);
- method @Deprecated public static long getUidTcpRxSegments(int);
- method @Deprecated public static long getUidTcpTxBytes(int);
- method @Deprecated public static long getUidTcpTxSegments(int);
- method public static long getUidTxBytes(int);
- method public static long getUidTxPackets(int);
- method @Deprecated public static long getUidUdpRxBytes(int);
- method @Deprecated public static long getUidUdpRxPackets(int);
- method @Deprecated public static long getUidUdpTxBytes(int);
- method @Deprecated public static long getUidUdpTxPackets(int);
- method public static void incrementOperationCount(int);
- method public static void incrementOperationCount(int, int);
- method public static void setThreadStatsTag(int);
- method public static void setThreadStatsUid(int);
- method public static void tagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
- method public static void tagFileDescriptor(java.io.FileDescriptor) throws java.io.IOException;
- method public static void tagSocket(java.net.Socket) throws java.net.SocketException;
- method public static void untagDatagramSocket(java.net.DatagramSocket) throws java.net.SocketException;
- method public static void untagFileDescriptor(java.io.FileDescriptor) throws java.io.IOException;
- method public static void untagSocket(java.net.Socket) throws java.net.SocketException;
- field public static final int UNSUPPORTED = -1; // 0xffffffff
- }
-
public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
method public abstract android.net.Uri.Builder buildUpon();
method public int compareTo(android.net.Uri);
@@ -25606,8 +25448,26 @@
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();
+ field public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
+ field public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER = "android.net.category.EVENT_DEACTIVATED_BY_USER";
+ field public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
+ field public static final String CATEGORY_EVENT_NETWORK_ERROR = "android.net.category.EVENT_NETWORK_ERROR";
+ field public static final int ERROR_CLASS_NOT_RECOVERABLE = 1; // 0x1
+ field public static final int ERROR_CLASS_RECOVERABLE = 2; // 0x2
+ field public static final int ERROR_CODE_NETWORK_IO = 3; // 0x3
+ field public static final int ERROR_CODE_NETWORK_LOST = 2; // 0x2
+ field public static final int ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT = 1; // 0x1
+ field public static final int ERROR_CODE_NETWORK_UNKNOWN_HOST = 0; // 0x0
+ field public static final String EXTRA_ERROR_CLASS = "android.net.extra.ERROR_CLASS";
+ field public static final String EXTRA_ERROR_CODE = "android.net.extra.ERROR_CODE";
+ field public static final String EXTRA_SESSION_KEY = "android.net.extra.SESSION_KEY";
+ field public static final String EXTRA_TIMESTAMP_MILLIS = "android.net.extra.TIMESTAMP_MILLIS";
+ field public static final String EXTRA_UNDERLYING_LINK_PROPERTIES = "android.net.extra.UNDERLYING_LINK_PROPERTIES";
+ field public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
+ field public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES = "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
}
public class VpnService extends android.app.Service {
@@ -26229,7 +26089,6 @@
field public static final String CATEGORY_PAYMENT = "payment";
field public static final String EXTRA_CATEGORY = "category";
field public static final String EXTRA_SERVICE_COMPONENT = "component";
- field public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
@@ -29464,7 +29323,7 @@
public class BaseBundle {
method public void clear();
method public boolean containsKey(String);
- method @Nullable public Object get(String);
+ method @Deprecated @Nullable public Object get(String);
method public boolean getBoolean(String);
method public boolean getBoolean(String, boolean);
method @Nullable public boolean[] getBooleanArray(@Nullable String);
@@ -29636,6 +29495,7 @@
field public static final int PREVIEW_SDK_INT;
field public static final String RELEASE;
field @NonNull public static final String RELEASE_OR_CODENAME;
+ field @NonNull public static final String RELEASE_OR_PREVIEW_DISPLAY;
field @Deprecated public static final String SDK;
field public static final int SDK_INT;
field public static final String SECURITY_PATCH;
@@ -29675,6 +29535,7 @@
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
}
@@ -29704,16 +29565,21 @@
method public float getFloat(String, float);
method @Nullable public float[] getFloatArray(@Nullable String);
method @Nullable public java.util.ArrayList<java.lang.Integer> getIntegerArrayList(@Nullable String);
- method @Nullable public <T extends android.os.Parcelable> T getParcelable(@Nullable String);
- method @Nullable public android.os.Parcelable[] getParcelableArray(@Nullable String);
- method @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayList(@Nullable String);
- method @Nullable public java.io.Serializable getSerializable(@Nullable String);
+ method @Deprecated @Nullable public <T extends android.os.Parcelable> T getParcelable(@Nullable String);
+ method @Nullable public <T> T getParcelable(@Nullable String, @NonNull Class<T>);
+ method @Deprecated @Nullable public android.os.Parcelable[] getParcelableArray(@Nullable String);
+ method @Nullable public <T> T[] getParcelableArray(@Nullable String, @NonNull Class<T>);
+ method @Deprecated @Nullable public <T extends android.os.Parcelable> java.util.ArrayList<T> getParcelableArrayList(@Nullable String);
+ method @Nullable public <T> java.util.ArrayList<T> getParcelableArrayList(@Nullable String, @NonNull Class<? extends T>);
+ method @Deprecated @Nullable public java.io.Serializable getSerializable(@Nullable String);
+ method @Nullable public <T extends java.io.Serializable> T getSerializable(@Nullable String, @NonNull Class<T>);
method public short getShort(String);
method public short getShort(String, short);
method @Nullable public short[] getShortArray(@Nullable String);
method @Nullable public android.util.Size getSize(@Nullable String);
method @Nullable public android.util.SizeF getSizeF(@Nullable String);
- method @Nullable public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(@Nullable String);
+ method @Deprecated @Nullable public <T extends android.os.Parcelable> android.util.SparseArray<T> getSparseParcelableArray(@Nullable String);
+ method @Nullable public <T> android.util.SparseArray<T> getSparseParcelableArray(@Nullable String, @NonNull Class<? extends T>);
method @Nullable public java.util.ArrayList<java.lang.String> getStringArrayList(@Nullable String);
method public boolean hasFileDescriptors();
method public void putAll(android.os.Bundle);
@@ -30269,6 +30135,9 @@
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>);
@@ -30309,6 +30178,9 @@
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);
@@ -30330,7 +30202,7 @@
method @Deprecated @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
method @Deprecated @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
- method @NonNull public <T> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader, @NonNull Class<T>);
+ method @NonNull public <T> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader, @NonNull Class<? extends T>);
method @Nullable public android.os.PersistableBundle readPersistableBundle();
method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
method @Deprecated @Nullable public java.io.Serializable readSerializable();
@@ -30352,6 +30224,7 @@
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[]);
@@ -30367,6 +30240,7 @@
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);
@@ -36183,6 +36057,28 @@
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();
}
@@ -39736,13 +39632,14 @@
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";
@@ -39818,6 +39715,7 @@
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";
@@ -39902,6 +39800,7 @@
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";
@@ -39945,6 +39844,7 @@
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
@@ -39968,14 +39868,24 @@
}
public static final class CarrierConfigManager.Ims {
+ field public static final String KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY = "ims.capability_type_call_composer_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY = "ims.capability_type_options_uce_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY = "ims.capability_type_presence_uce_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY = "ims.capability_type_sms_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY = "ims.capability_type_ut_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY = "ims.capability_type_video_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY = "ims.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_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL = "ims.use_sip_uri_for_presence_subscribe_bool";
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
}
@@ -41052,16 +40962,16 @@
ctor @Deprecated public ServiceState(android.os.Parcel);
method protected void copyFrom(android.telephony.ServiceState);
method public int describeContents();
- method public int getCdmaNetworkId();
- method public int getCdmaSystemId();
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public int getCdmaNetworkId();
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public int getCdmaSystemId();
method public int[] getCellBandwidths();
method public int getChannelNumber();
method public int getDuplexMode();
method public boolean getIsManualSelection();
method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
- method public String getOperatorAlphaLong();
- method public String getOperatorAlphaShort();
- method public String getOperatorNumeric();
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorAlphaLong();
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorAlphaShort();
+ method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public String getOperatorNumeric();
method public boolean getRoaming();
method public int getState();
method public boolean isSearching();
@@ -41598,6 +41508,7 @@
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();
@@ -41658,6 +41569,7 @@
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();
@@ -41703,6 +41615,7 @@
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);
@@ -41739,6 +41652,8 @@
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
@@ -41809,6 +41724,26 @@
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
@@ -42390,6 +42325,7 @@
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";
@@ -42640,6 +42576,23 @@
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;
}
@@ -42680,6 +42633,27 @@
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 9e26908..a9f0d2e 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -51,31 +51,6 @@
}
-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;
- method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
- method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long);
- method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
- method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
- method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long);
- 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 {
- method public void onThresholdReached(@NonNull android.net.NetworkTemplate);
- }
-
-}
-
package android.content {
public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
@@ -140,7 +115,7 @@
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);
@@ -150,18 +125,18 @@
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 {
@@ -218,52 +193,26 @@
package android.net {
- public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
- ctor public EthernetNetworkSpecifier(@NonNull String);
- method public int describeContents();
- method @Nullable public String getInterfaceName();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkSpecifier> CREATOR;
+ public class EthernetManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void addInterfaceStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.InterfaceStateListener);
+ method public void removeInterfaceStateListener(@NonNull android.net.EthernetManager.InterfaceStateListener);
+ method public void setIncludeTestInterfaces(boolean);
+ field public static final int ROLE_CLIENT = 1; // 0x1
+ field public static final int ROLE_NONE = 0; // 0x0
+ field public static final int ROLE_SERVER = 2; // 0x2
+ field public static final int STATE_ABSENT = 0; // 0x0
+ field public static final int STATE_LINK_DOWN = 1; // 0x1
+ field public static final int STATE_LINK_UP = 2; // 0x2
}
- public final class IpSecManager {
- field public static final int DIRECTION_FWD = 2; // 0x2
- }
-
- public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable {
- method public int getResourceId();
+ public static interface EthernetManager.InterfaceStateListener {
+ method public void onInterfaceStateChanged(@NonNull String, int, int, @Nullable android.net.IpConfiguration);
}
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();
- method @Nullable public String getSubscriberId();
- method public int getType();
- method @Nullable public String getWifiNetworkKey();
- method public boolean isDefaultNetwork();
- method public boolean isMetered();
- method public boolean isRoaming();
- }
-
- public static final class NetworkIdentity.Builder {
- ctor public NetworkIdentity.Builder();
- method @NonNull public android.net.NetworkIdentity build();
- method @NonNull public android.net.NetworkIdentity.Builder clearRatType();
- method @NonNull public android.net.NetworkIdentity.Builder setDefaultNetwork(boolean);
- method @NonNull public android.net.NetworkIdentity.Builder setMetered(boolean);
- method @NonNull public android.net.NetworkIdentity.Builder setNetworkStateSnapshot(@NonNull android.net.NetworkStateSnapshot);
- method @NonNull public android.net.NetworkIdentity.Builder setOemManaged(int);
- method @NonNull public android.net.NetworkIdentity.Builder setRatType(int);
- method @NonNull public android.net.NetworkIdentity.Builder setRoaming(boolean);
- method @NonNull public android.net.NetworkIdentity.Builder setSubscriberId(@Nullable String);
- method @NonNull public android.net.NetworkIdentity.Builder setType(int);
- method @NonNull public android.net.NetworkIdentity.Builder setWifiNetworkKey(@Nullable String);
- }
-
public class NetworkPolicyManager {
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getMultipathPreference(@NonNull android.net.Network);
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getRestrictBackgroundStatus(int);
@@ -279,94 +228,6 @@
method public default void onUidBlockedReasonChanged(int, int);
}
- public final class NetworkStateSnapshot implements android.os.Parcelable {
- ctor public NetworkStateSnapshot(@NonNull android.net.Network, @NonNull android.net.NetworkCapabilities, @NonNull android.net.LinkProperties, @Nullable String, int);
- method public int describeContents();
- method public int getLegacyType();
- method @NonNull public android.net.LinkProperties getLinkProperties();
- method @NonNull public android.net.Network getNetwork();
- method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
- method @Nullable public String getSubscriberId();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- 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();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStatsHistory> CREATOR;
- }
-
- public static final class NetworkStatsHistory.Builder {
- ctor public NetworkStatsHistory.Builder(long, int);
- method @NonNull public android.net.NetworkStatsHistory.Builder addEntry(@NonNull android.net.NetworkStatsHistory.Entry);
- method @NonNull public android.net.NetworkStatsHistory build();
- }
-
- public static final class NetworkStatsHistory.Entry {
- ctor public NetworkStatsHistory.Entry(long, long, long, long, long, long, long);
- method public long getActiveTime();
- method public long getBucketStart();
- method public long getOperations();
- method public long getRxBytes();
- method public long getRxPackets();
- method public long getTxBytes();
- method public long getTxPackets();
- }
-
- public final class NetworkTemplate implements android.os.Parcelable {
- method public int describeContents();
- method public int getDefaultNetworkStatus();
- method public int getMatchRule();
- method public int getMeteredness();
- method public int getOemManaged();
- method public int getRatType();
- 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
- field public static final int MATCH_CARRIER = 10; // 0xa
- field public static final int MATCH_ETHERNET = 5; // 0x5
- field public static final int MATCH_MOBILE = 1; // 0x1
- field public static final int MATCH_WIFI = 4; // 0x4
- field public static final int NETWORK_TYPE_ALL = -1; // 0xffffffff
- field public static final int OEM_MANAGED_ALL = -1; // 0xffffffff
- field public static final int OEM_MANAGED_NO = 0; // 0x0
- field public static final int OEM_MANAGED_PAID = 1; // 0x1
- field public static final int OEM_MANAGED_PRIVATE = 2; // 0x2
- field public static final int OEM_MANAGED_YES = -2; // 0xfffffffe
- }
-
- public static final class NetworkTemplate.Builder {
- ctor public NetworkTemplate.Builder(int);
- method @NonNull public android.net.NetworkTemplate build();
- method @NonNull public android.net.NetworkTemplate.Builder setDefaultNetworkStatus(int);
- method @NonNull public android.net.NetworkTemplate.Builder setMeteredness(int);
- method @NonNull public android.net.NetworkTemplate.Builder setOemManaged(int);
- method @NonNull public android.net.NetworkTemplate.Builder setRatType(int);
- method @NonNull public android.net.NetworkTemplate.Builder setRoaming(int);
- method @NonNull public android.net.NetworkTemplate.Builder setSubscriberIds(@NonNull java.util.Set<java.lang.String>);
- method @NonNull public android.net.NetworkTemplate.Builder setWifiNetworkKeys(@NonNull java.util.Set<java.lang.String>);
- }
-
public class NetworkWatchlistManager {
method @Nullable public byte[] getWatchlistConfigHash();
}
@@ -385,21 +246,6 @@
method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo);
}
- public class TrafficStats {
- method public static void attachSocketTagger();
- method public static void init(@NonNull android.content.Context);
- }
-
- public final class UnderlyingNetworkInfo implements android.os.Parcelable {
- ctor public UnderlyingNetworkInfo(int, @NonNull String, @NonNull java.util.List<java.lang.String>);
- method public int describeContents();
- method @NonNull public String getInterface();
- method public int getOwnerUid();
- method @NonNull public java.util.List<java.lang.String> getUnderlyingInterfaces();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.UnderlyingNetworkInfo> CREATOR;
- }
-
public class VpnManager {
field public static final int TYPE_VPN_LEGACY = 3; // 0x3
field public static final int TYPE_VPN_NONE = -1; // 0xffffffff
diff --git a/core/api/removed.txt b/core/api/removed.txt
index bf86422..32a4673 100644
--- a/core/api/removed.txt
+++ b/core/api/removed.txt
@@ -260,10 +260,6 @@
method @Deprecated public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
}
- public class TrafficStats {
- method @Deprecated public static void setThreadStatsUidSelf();
- }
-
}
package android.os {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 5951151..9db26bd 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -145,6 +145,7 @@
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";
@@ -1851,13 +1852,6 @@
field public static final String SERVICE_INTERFACE = "android.app.usage.CacheQuotaService";
}
- public class NetworkStatsManager {
- method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getMobileUidStats();
- method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getWifiUidStats();
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
- method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
- }
-
public static final class UsageEvents.Event {
method public int getInstanceId();
method @Nullable public String getNotificationChannelId();
@@ -1995,6 +1989,7 @@
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";
@@ -2953,6 +2948,7 @@
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 {
@@ -7020,7 +7016,10 @@
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 {
@@ -7032,21 +7031,27 @@
method public void release();
}
- 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;
+ 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 static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
- method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
- method public void close();
- method @NonNull public String getInterfaceName();
- method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull java.net.InetAddress, int) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void setUnderlyingNetwork(@NonNull android.net.Network) throws java.io.IOException;
+ public final class EthernetNetworkUpdateRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.net.IpConfiguration getIpConfiguration();
+ 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 static class IpSecTransform.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecTransform buildTunnelModeTransform(@NonNull java.net.InetAddress, @NonNull android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
+ public static final class EthernetNetworkUpdateRequest.Builder {
+ ctor public EthernetNetworkUpdateRequest.Builder();
+ ctor public EthernetNetworkUpdateRequest.Builder(@NonNull android.net.EthernetNetworkUpdateRequest);
+ method @NonNull public android.net.EthernetNetworkUpdateRequest build();
+ method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setIpConfiguration(@NonNull android.net.IpConfiguration);
+ method @NonNull public android.net.EthernetNetworkUpdateRequest.Builder setNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
}
public final class MatchAllNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
@@ -7110,48 +7115,6 @@
field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
}
- public final class NetworkStats implements java.lang.Iterable<android.net.NetworkStats.Entry> android.os.Parcelable {
- ctor public NetworkStats(long, int);
- method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
- method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
- method public int describeContents();
- method @NonNull public java.util.Iterator<android.net.NetworkStats.Entry> iterator();
- method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStats> CREATOR;
- field public static final int DEFAULT_NETWORK_ALL = -1; // 0xffffffff
- field public static final int DEFAULT_NETWORK_NO = 0; // 0x0
- field public static final int DEFAULT_NETWORK_YES = 1; // 0x1
- field public static final String IFACE_VT = "vt_data0";
- field public static final int METERED_ALL = -1; // 0xffffffff
- field public static final int METERED_NO = 0; // 0x0
- field public static final int METERED_YES = 1; // 0x1
- field public static final int ROAMING_ALL = -1; // 0xffffffff
- field public static final int ROAMING_NO = 0; // 0x0
- field public static final int ROAMING_YES = 1; // 0x1
- field public static final int SET_ALL = -1; // 0xffffffff
- field public static final int SET_DEFAULT = 0; // 0x0
- field public static final int SET_FOREGROUND = 1; // 0x1
- field public static final int TAG_NONE = 0; // 0x0
- field public static final int UID_ALL = -1; // 0xffffffff
- field public static final int UID_TETHERING = -5; // 0xfffffffb
- }
-
- public static class NetworkStats.Entry {
- ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long);
- method public int getDefaultNetwork();
- method public int getMetered();
- method public long getOperations();
- method public int getRoaming();
- method public long getRxBytes();
- method public long getRxPackets();
- method public int getSet();
- method public int getTag();
- method public long getTxBytes();
- method public long getTxPackets();
- method public int getUid();
- }
-
public class RssiCurve implements android.os.Parcelable {
ctor public RssiCurve(int, int, byte[]);
ctor public RssiCurve(int, int, byte[], int);
@@ -7183,19 +7146,6 @@
field public final android.net.RssiCurve rssiCurve;
}
- public class TrafficStats {
- method public static void setThreadStatsTagApp();
- method public static void setThreadStatsTagBackup();
- method public static void setThreadStatsTagDownload();
- method public static void setThreadStatsTagRestore();
- field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = -113; // 0xffffff8f
- field public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = -128; // 0xffffff80
- field public static final int TAG_NETWORK_STACK_RANGE_END = -257; // 0xfffffeff
- field public static final int TAG_NETWORK_STACK_RANGE_START = -768; // 0xfffffd00
- field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = -241; // 0xffffff0f
- field public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = -256; // 0xffffff00
- }
-
public abstract class Uri implements java.lang.Comparable<android.net.Uri> android.os.Parcelable {
method @NonNull public String toSafeString();
}
@@ -7376,23 +7326,6 @@
}
-package android.net.netstats.provider {
-
- public abstract class NetworkStatsProvider {
- ctor public NetworkStatsProvider();
- method public void notifyAlertReached();
- method public void notifyLimitReached();
- method public void notifyStatsUpdated(int, @NonNull android.net.NetworkStats, @NonNull android.net.NetworkStats);
- method public void notifyWarningReached();
- method public abstract void onRequestStatsUpdate(int);
- method public abstract void onSetAlert(long);
- method public abstract void onSetLimit(@NonNull String, long);
- method public void onSetWarningAndLimit(@NonNull String, long, long);
- field public static final int QUOTA_UNLIMITED = -1; // 0xffffffff
- }
-
-}
-
package android.net.sip {
@Deprecated public class SipAudioCall {
@@ -7828,6 +7761,7 @@
}
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;
}
@@ -9000,6 +8934,7 @@
field public static final String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
field public static final String ACTION_TETHER_PROVISIONING_UI = "android.settings.TETHER_PROVISIONING_UI";
field public static final String ACTION_TETHER_SETTINGS = "android.settings.TETHER_SETTINGS";
+ field public static final String ACTION_TETHER_UNSUPPORTED_CARRIER_UI = "android.settings.TETHER_UNSUPPORTED_CARRIER_UI";
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
@@ -10125,8 +10060,6 @@
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);
}
@@ -11667,7 +11600,6 @@
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>);
@@ -11710,7 +11642,6 @@
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();
@@ -11761,7 +11692,6 @@
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);
@@ -11811,10 +11741,8 @@
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
@@ -11853,26 +11781,6 @@
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
@@ -12898,13 +12806,21 @@
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();
@@ -13128,18 +13044,16 @@
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);
@@ -13186,6 +13100,7 @@
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 {
@@ -13253,6 +13168,7 @@
method @Nullable public android.telephony.ims.RcsContactPresenceTuple getCapabilityTuple(@NonNull String);
method @NonNull public java.util.List<android.telephony.ims.RcsContactPresenceTuple> getCapabilityTuples();
method @NonNull public android.net.Uri getContactUri();
+ method @Nullable public android.net.Uri getEntityUri();
method @NonNull public java.util.Set<java.lang.String> getFeatureTags();
method public int getRequestResult();
method public int getSourceType();
@@ -13281,6 +13197,7 @@
method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuple(@NonNull android.telephony.ims.RcsContactPresenceTuple);
method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuples(@NonNull java.util.List<android.telephony.ims.RcsContactPresenceTuple>);
method @NonNull public android.telephony.ims.RcsContactUceCapability build();
+ method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder setEntityUri(@NonNull android.net.Uri);
}
public class RcsUceAdapter {
@@ -13522,6 +13439,7 @@
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);
@@ -13555,7 +13473,7 @@
}
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);
@@ -13572,9 +13490,6 @@
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
}
}
@@ -13660,6 +13575,7 @@
}
public class ImsConfigImplBase {
+ ctor public ImsConfigImplBase(@NonNull java.util.concurrent.Executor);
ctor public ImsConfigImplBase();
method public int getConfigInt(int);
method public String getConfigString(int);
@@ -13712,6 +13628,7 @@
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);
@@ -13722,11 +13639,6 @@
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 {
@@ -13824,6 +13736,7 @@
}
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-lint-baseline.txt b/core/api/system-lint-baseline.txt
index b435acf..97eda7a 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -1,12 +1,6 @@
// Baseline format: 1.0
ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
-
-
-BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
- Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
-
-
ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener`
@@ -15,8 +9,6 @@
GenericException: android.hardware.location.ContextHubClient#finalize():
-GenericException: android.net.IpSecManager.IpSecTunnelInterface#finalize():
-
GenericException: android.service.autofill.augmented.FillWindow#finalize():
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 18ceb25..73caa5d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -635,10 +635,6 @@
package android.app.usage {
- public class NetworkStatsManager {
- method public void setPollForce(boolean);
- }
-
public class StorageStatsManager {
method public boolean isQuotaSupported(@NonNull java.util.UUID);
method public boolean isReservedSupported(@NonNull java.util.UUID);
@@ -1573,14 +1569,6 @@
package android.net {
- public class EthernetManager {
- method public void setIncludeTestInterfaces(boolean);
- }
-
- public final class IpSecManager {
- field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0
- }
-
public class NetworkPolicyManager {
method public boolean getRestrictBackground();
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean);
@@ -1597,13 +1585,6 @@
method @Nullable public byte[] getWatchlistConfigHash();
}
- public class TrafficStats {
- method public static long getLoopbackRxBytes();
- method public static long getLoopbackRxPackets();
- method public static long getLoopbackTxBytes();
- method public static long getLoopbackTxPackets();
- }
-
}
package android.os {
@@ -1707,8 +1688,11 @@
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 {
@@ -2193,8 +2177,8 @@
}
public class KeyStoreException extends java.lang.Exception {
- ctor public KeyStoreException(int, String);
method public int getErrorCode();
+ method public static boolean hasFailureInfoForError(int);
}
}
@@ -2497,7 +2481,6 @@
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 72a432e..27f3fc5 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -149,7 +149,6 @@
filegroup {
name: "framework-services-net-module-wifi-shared-srcs",
srcs: [
- "android/net/DhcpResults.java",
"android/util/LocalLog.java",
],
}
@@ -165,6 +164,18 @@
"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/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index f9739a4..6a0a289 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -44,7 +44,6 @@
import android.app.trust.TrustManager;
import android.app.usage.IStorageStatsManager;
import android.app.usage.IUsageStatsManager;
-import android.app.usage.NetworkStatsManager;
import android.app.usage.StorageStatsManager;
import android.app.usage.UsageStatsManager;
import android.apphibernation.AppHibernationManager;
@@ -128,12 +127,9 @@
import android.net.ConnectivityFrameworkInitializerTiramisu;
import android.net.EthernetManager;
import android.net.IEthernetManager;
-import android.net.IIpSecService;
import android.net.INetworkPolicyManager;
-import android.net.INetworkStatsService;
import android.net.IPacProxyManager;
import android.net.IVpnManager;
-import android.net.IpSecManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkScoreManager;
import android.net.NetworkWatchlistManager;
@@ -420,15 +416,6 @@
return new VcnManager(ctx, service);
}});
- registerService(Context.IPSEC_SERVICE, IpSecManager.class,
- new CachedServiceFetcher<IpSecManager>() {
- @Override
- public IpSecManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getService(Context.IPSEC_SERVICE);
- IIpSecService service = IIpSecService.Stub.asInterface(b);
- return new IpSecManager(ctx, service);
- }});
-
registerService(Context.COUNTRY_DETECTOR, CountryDetector.class,
new StaticServiceFetcher<CountryDetector>() {
@Override
@@ -978,17 +965,6 @@
return new UsageStatsManager(ctx.getOuterContext(), service);
}});
- registerService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class,
- new CachedServiceFetcher<NetworkStatsManager>() {
- @Override
- public NetworkStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- // TODO: Replace with an initializer in the module, see
- // {@code ConnectivityFrameworkInitializer}.
- final INetworkStatsService service = INetworkStatsService.Stub.asInterface(
- ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
- return new NetworkStatsManager(ctx.getOuterContext(), service);
- }});
-
registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class,
new StaticServiceFetcher<PersistentDataBlockManager>() {
@Override
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 6cfa39c..ab64596 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1452,18 +1452,27 @@
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 @@
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/assist/OWNERS b/core/java/android/app/assist/OWNERS
index 46b5ea0..e857c72 100644
--- a/core/java/android/app/assist/OWNERS
+++ b/core/java/android/app/assist/OWNERS
@@ -1,7 +1,5 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/app/contentsuggestions/OWNERS b/core/java/android/app/contentsuggestions/OWNERS
index 482abb2..cf54c2a 100644
--- a/core/java/android/app/contentsuggestions/OWNERS
+++ b/core/java/android/app/contentsuggestions/OWNERS
@@ -1,9 +1,7 @@
# Bug component: 643919
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index 8e281c0..a7c0e5c 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -50,16 +50,17 @@
* <p>The creator of an external suggestion is expected to be separate Android process, e.g. a
* process integrating with the external time source via a HAL or local network. The creator must
* capture the elapsed realtime reference clock, e.g. via {@link SystemClock#elapsedRealtime()},
- * when the UTC time is first obtained (usually under a wakelock). This enables Android to adjust
- * for latency introduced between suggestion creation and eventual use. Adjustments for other
+ * when the Unix epoch time is first obtained (usually under a wakelock). This enables Android to
+ * adjust for latency introduced between suggestion creation and eventual use. Adjustments for other
* sources of latency, i.e. those before the external time suggestion is created, must be handled by
* the creator.
*
* <p>{@code elapsedRealtimeMillis} and {@code suggestionMillis} represent the suggested time.
- * {@code suggestionMillis} is the number of milliseconds elapsed since 1/1/1970 00:00:00 UTC.
- * {@code elapsedRealtimeMillis} is the value of the elapsed realtime clock when {@code
- * suggestionMillis} was established. Note that the elapsed realtime clock is considered accurate
- * but it is volatile, so time suggestions cannot be persisted across device resets.
+ * {@code suggestionMillis} is the number of milliseconds elapsed since 1/1/1970 00:00:00 UTC
+ * according to the Unix time scale. {@code elapsedRealtimeMillis} is the value of the elapsed
+ * realtime clock when {@code suggestionMillis} was established. Note that the elapsed realtime
+ * clock is considered accurate but it is volatile, so time suggestions cannot be persisted across
+ * device resets.
*
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
* record why the suggestion exists and how it was entered. This information exists only to aid in
@@ -83,7 +84,7 @@
};
@NonNull
- private final TimestampedValue<Long> mUtcTime;
+ private final TimestampedValue<Long> mUnixEpochTime;
@Nullable
private ArrayList<String> mDebugInfo;
@@ -92,12 +93,12 @@
* ExternalTimeSuggestion} for more details.
*
* @param elapsedRealtimeMillis the elapsed realtime clock reference for the suggestion
- * @param suggestionMillis the suggested UTC time in milliseconds since the start of the
+ * @param suggestionMillis the suggested time in milliseconds since the start of the
* Unix epoch
*/
public ExternalTimeSuggestion(@ElapsedRealtimeLong long elapsedRealtimeMillis,
@CurrentTimeMillisLong long suggestionMillis) {
- mUtcTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
+ mUnixEpochTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
}
private static ExternalTimeSuggestion createFromParcel(Parcel in) {
@@ -117,7 +118,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUtcTime, 0);
+ dest.writeParcelable(mUnixEpochTime, 0);
dest.writeList(mDebugInfo);
}
@@ -125,8 +126,8 @@
* {@hide}
*/
@NonNull
- public TimestampedValue<Long> getUtcTime() {
- return mUtcTime;
+ public TimestampedValue<Long> getUnixEpochTime() {
+ return mUnixEpochTime;
}
/**
@@ -160,17 +161,18 @@
return false;
}
ExternalTimeSuggestion that = (ExternalTimeSuggestion) o;
- return Objects.equals(mUtcTime, that.mUtcTime);
+ return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
}
@Override
public int hashCode() {
- return Objects.hash(mUtcTime);
+ return Objects.hash(mUnixEpochTime);
}
@Override
public String toString() {
- return "ExternalTimeSuggestion{" + "mUtcTime=" + mUtcTime + ", mDebugInfo=" + mDebugInfo
+ return "ExternalTimeSuggestion{" + "mUnixEpochTime=" + mUnixEpochTime
+ + ", mDebugInfo=" + mDebugInfo
+ '}';
}
}
diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.java b/core/java/android/app/timedetector/GnssTimeSuggestion.java
index 6478a2d..34f4565 100644
--- a/core/java/android/app/timedetector/GnssTimeSuggestion.java
+++ b/core/java/android/app/timedetector/GnssTimeSuggestion.java
@@ -31,11 +31,11 @@
/**
* A time signal from a GNSS source.
*
- * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
- * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
- * elapsed realtime clock when the {@code utcTime.value} was established.
- * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
- * suggestions cannot be persisted across device resets.
+ * <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system. The {@code
+ * unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when the {@code
+ * unixEpochTime.value} was established. Note that the elapsed realtime clock is considered accurate
+ * but it is volatile, so time suggestions cannot be persisted across device resets.
*
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
* record why the suggestion exists and how it was entered. This information exists only to aid in
@@ -57,17 +57,17 @@
}
};
- @NonNull private final TimestampedValue<Long> mUtcTime;
+ @NonNull private final TimestampedValue<Long> mUnixEpochTime;
@Nullable private ArrayList<String> mDebugInfo;
- public GnssTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
- mUtcTime = Objects.requireNonNull(utcTime);
- Objects.requireNonNull(utcTime.getValue());
+ public GnssTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
+ mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
+ Objects.requireNonNull(unixEpochTime.getValue());
}
private static GnssTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
- GnssTimeSuggestion suggestion = new GnssTimeSuggestion(utcTime);
+ TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
+ GnssTimeSuggestion suggestion = new GnssTimeSuggestion(unixEpochTime);
@SuppressWarnings("unchecked")
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
@@ -81,13 +81,13 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUtcTime, 0);
+ dest.writeParcelable(mUnixEpochTime, 0);
dest.writeList(mDebugInfo);
}
@NonNull
- public TimestampedValue<Long> getUtcTime() {
- return mUtcTime;
+ public TimestampedValue<Long> getUnixEpochTime() {
+ return mUnixEpochTime;
}
@NonNull
@@ -117,18 +117,18 @@
return false;
}
GnssTimeSuggestion that = (GnssTimeSuggestion) o;
- return Objects.equals(mUtcTime, that.mUtcTime);
+ return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
}
@Override
public int hashCode() {
- return Objects.hash(mUtcTime);
+ return Objects.hash(mUnixEpochTime);
}
@Override
public String toString() {
return "GnssTimeSuggestion{"
- + "mUtcTime=" + mUtcTime
+ + "mUnixEpochTime=" + mUnixEpochTime
+ ", mDebugInfo=" + mDebugInfo
+ '}';
}
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
index 299e951..76db33b 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -31,9 +31,9 @@
/**
* A time signal from a manual (user provided) source.
*
- * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
- * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
- * elapsed realtime clock when the {@code utcTime.value} was established.
+ * <p>{@code unixEpochTime} is the suggested time. The {@code unixEpochTime.value} is the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code unixEpochTime.referenceTimeMillis}
+ * is the value of the elapsed realtime clock when the {@code unixEpochTime.value} was established.
* Note that the elapsed realtime clock is considered accurate but it is volatile, so time
* suggestions cannot be persisted across device resets.
*
@@ -57,17 +57,17 @@
}
};
- @NonNull private final TimestampedValue<Long> mUtcTime;
+ @NonNull private final TimestampedValue<Long> mUnixEpochTime;
@Nullable private ArrayList<String> mDebugInfo;
- public ManualTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
- mUtcTime = Objects.requireNonNull(utcTime);
- Objects.requireNonNull(utcTime.getValue());
+ public ManualTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
+ mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
+ Objects.requireNonNull(unixEpochTime.getValue());
}
private static ManualTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
- ManualTimeSuggestion suggestion = new ManualTimeSuggestion(utcTime);
+ TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
+ ManualTimeSuggestion suggestion = new ManualTimeSuggestion(unixEpochTime);
@SuppressWarnings("unchecked")
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
@@ -81,13 +81,13 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUtcTime, 0);
+ dest.writeParcelable(mUnixEpochTime, 0);
dest.writeList(mDebugInfo);
}
@NonNull
- public TimestampedValue<Long> getUtcTime() {
- return mUtcTime;
+ public TimestampedValue<Long> getUnixEpochTime() {
+ return mUnixEpochTime;
}
@NonNull
@@ -117,18 +117,18 @@
return false;
}
ManualTimeSuggestion that = (ManualTimeSuggestion) o;
- return Objects.equals(mUtcTime, that.mUtcTime);
+ return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
}
@Override
public int hashCode() {
- return Objects.hash(mUtcTime);
+ return Objects.hash(mUnixEpochTime);
}
@Override
public String toString() {
return "ManualTimeSuggestion{"
- + "mUtcTime=" + mUtcTime
+ + "mUnixEpochTime=" + mUnixEpochTime
+ ", mDebugInfo=" + mDebugInfo
+ '}';
}
diff --git a/core/java/android/app/timedetector/NetworkTimeSuggestion.java b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
index a5259c2..e22f1d6e 100644
--- a/core/java/android/app/timedetector/NetworkTimeSuggestion.java
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
@@ -31,11 +31,12 @@
/**
* A time signal from a network time source like NTP.
*
- * <p>{@code utcTime} contains the suggested time. The {@code utcTime.value} is the number of
- * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the
- * value of the elapsed realtime clock when the {@code utcTime.value} was established.
- * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
- * suggestions cannot be persisted across device resets.
+ * <p>{@code unixEpochTime} contains the suggested time. The {@code unixEpochTime.value} is the
+ * number of milliseconds elapsed since 1/1/1970 00:00:00 UTC according to the Unix time system.
+ * The {@code unixEpochTime.referenceTimeMillis} is the value of the elapsed realtime clock when
+ * the {@code unixEpochTime.value} was established. Note that the elapsed realtime clock is
+ * considered accurate but it is volatile, so time suggestions cannot be persisted across device
+ * resets.
*
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
* record why the suggestion exists and how it was determined. This information exists only to aid
@@ -57,17 +58,17 @@
}
};
- @NonNull private final TimestampedValue<Long> mUtcTime;
+ @NonNull private final TimestampedValue<Long> mUnixEpochTime;
@Nullable private ArrayList<String> mDebugInfo;
- public NetworkTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
- mUtcTime = Objects.requireNonNull(utcTime);
- Objects.requireNonNull(utcTime.getValue());
+ public NetworkTimeSuggestion(@NonNull TimestampedValue<Long> unixEpochTime) {
+ mUnixEpochTime = Objects.requireNonNull(unixEpochTime);
+ Objects.requireNonNull(unixEpochTime.getValue());
}
private static NetworkTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
- NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(utcTime);
+ TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
+ NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(unixEpochTime);
@SuppressWarnings("unchecked")
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
@@ -81,13 +82,13 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeParcelable(mUtcTime, 0);
+ dest.writeParcelable(mUnixEpochTime, 0);
dest.writeList(mDebugInfo);
}
@NonNull
- public TimestampedValue<Long> getUtcTime() {
- return mUtcTime;
+ public TimestampedValue<Long> getUnixEpochTime() {
+ return mUnixEpochTime;
}
@NonNull
@@ -117,18 +118,18 @@
return false;
}
NetworkTimeSuggestion that = (NetworkTimeSuggestion) o;
- return Objects.equals(mUtcTime, that.mUtcTime);
+ return Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
}
@Override
public int hashCode() {
- return Objects.hash(mUtcTime);
+ return Objects.hash(mUnixEpochTime);
}
@Override
public String toString() {
return "NetworkTimeSuggestion{"
- + "mUtcTime=" + mUtcTime
+ + "mUnixEpochTime=" + mUnixEpochTime
+ ", mDebugInfo=" + mDebugInfo
+ '}';
}
diff --git a/core/java/android/app/timedetector/TelephonyTimeSuggestion.java b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
index 6c3a304..4ff7517 100644
--- a/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
+++ b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
@@ -34,12 +34,12 @@
* <p>{@code slotIndex} identifies the suggestion source. This enables detection logic to identify
* suggestions from the same source when there are several in use.
*
- * <p>{@code utcTime}. When not {@code null}, the {@code utcTime.value} is the number of
- * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the
- * value of the elapsed realtime clock when the {@code utcTime.value} was established.
+ * <p>{@code unixEpochTime}. When not {@code null}, the {@code unixEpochTime.value} is the number of
+ * milliseconds elapsed since 1/1/1970 00:00:00 UTC. The {@code unixEpochTime.referenceTimeMillis}
+ * is the value of the elapsed realtime clock when the {@code unixEpochTime.value} was established.
* Note that the elapsed realtime clock is considered accurate but it is volatile, so time
- * suggestions cannot be persisted across device resets. {@code utcTime} can be {@code null} to
- * indicate that the telephony source has entered an "un-opinionated" state and any previous
+ * suggestions cannot be persisted across device resets. {@code unixEpochTime} can be {@code null}
+ * to indicate that the telephony source has entered an "un-opinionated" state and any previous
* suggestion from the source is being withdrawn.
*
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
@@ -65,19 +65,20 @@
};
private final int mSlotIndex;
- @Nullable private final TimestampedValue<Long> mUtcTime;
+ @Nullable private final TimestampedValue<Long> mUnixEpochTime;
@Nullable private ArrayList<String> mDebugInfo;
private TelephonyTimeSuggestion(Builder builder) {
mSlotIndex = builder.mSlotIndex;
- mUtcTime = builder.mUtcTime;
+ mUnixEpochTime = builder.mUnixEpochTime;
mDebugInfo = builder.mDebugInfo != null ? new ArrayList<>(builder.mDebugInfo) : null;
}
private static TelephonyTimeSuggestion createFromParcel(Parcel in) {
int slotIndex = in.readInt();
+ TimestampedValue<Long> unixEpochTime = in.readParcelable(null /* classLoader */);
TelephonyTimeSuggestion suggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
- .setUtcTime(in.readParcelable(null /* classLoader */))
+ .setUnixEpochTime(unixEpochTime)
.build();
@SuppressWarnings("unchecked")
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
@@ -95,7 +96,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mSlotIndex);
- dest.writeParcelable(mUtcTime, 0);
+ dest.writeParcelable(mUnixEpochTime, 0);
dest.writeList(mDebugInfo);
}
@@ -111,11 +112,11 @@
/**
* Returns the suggested time or {@code null} if there isn't one.
*
- * <p>See {@link TelephonyTimeSuggestion} for more information about {@code utcTime}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code unixEpochTime}.
*/
@Nullable
- public TimestampedValue<Long> getUtcTime() {
- return mUtcTime;
+ public TimestampedValue<Long> getUnixEpochTime() {
+ return mUnixEpochTime;
}
/**
@@ -163,19 +164,19 @@
}
TelephonyTimeSuggestion that = (TelephonyTimeSuggestion) o;
return mSlotIndex == that.mSlotIndex
- && Objects.equals(mUtcTime, that.mUtcTime);
+ && Objects.equals(mUnixEpochTime, that.mUnixEpochTime);
}
@Override
public int hashCode() {
- return Objects.hash(mSlotIndex, mUtcTime);
+ return Objects.hash(mSlotIndex, mUnixEpochTime);
}
@Override
public String toString() {
return "TelephonyTimeSuggestion{"
+ "mSlotIndex='" + mSlotIndex + '\''
- + ", mUtcTime=" + mUtcTime
+ + ", mUnixEpochTime=" + mUnixEpochTime
+ ", mDebugInfo=" + mDebugInfo
+ '}';
}
@@ -187,7 +188,7 @@
*/
public static final class Builder {
private final int mSlotIndex;
- @Nullable private TimestampedValue<Long> mUtcTime;
+ @Nullable private TimestampedValue<Long> mUnixEpochTime;
@Nullable private List<String> mDebugInfo;
/**
@@ -202,16 +203,16 @@
/**
* Returns the builder for call chaining.
*
- * <p>See {@link TelephonyTimeSuggestion} for more information about {@code utcTime}.
+ * <p>See {@link TelephonyTimeSuggestion} for more information about {@code unixEpochTime}.
*/
@NonNull
- public Builder setUtcTime(@Nullable TimestampedValue<Long> utcTime) {
- if (utcTime != null) {
- // utcTime can be null, but the value it holds cannot.
- Objects.requireNonNull(utcTime.getValue());
+ public Builder setUnixEpochTime(@Nullable TimestampedValue<Long> unixEpochTime) {
+ if (unixEpochTime != null) {
+ // unixEpochTime can be null, but the value it holds cannot.
+ Objects.requireNonNull(unixEpochTime.getValue());
}
- mUtcTime = utcTime;
+ mUnixEpochTime = unixEpochTime;
return this;
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 98e124d..7cb0934 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3434,7 +3434,7 @@
public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
/**
- * Connect to an application service, creating it if needed. This defines
+ * Connects to an application service, creating it if needed. This defines
* a dependency between your application and the service. The given
* <var>conn</var> will receive the service object when it is created and be
* told if it dies and restarts. The service will be considered required
@@ -3449,11 +3449,8 @@
* will be invoked instead of
* {@link ServiceConnection#onServiceConnected(ComponentName, IBinder) onServiceConnected()}.
*
- * <p>This method will throw {@link SecurityException} if the calling app does not
- * have permission to bind to the given service.
- *
- * <p class="note">Note: this method <em>cannot be called from a
- * {@link BroadcastReceiver} component</em>. A pattern you can use to
+ * <p class="note"><b>Note:</b> This method <em>cannot</em> be called from a
+ * {@link BroadcastReceiver} component. A pattern you can use to
* communicate from a BroadcastReceiver to a Service is to call
* {@link #startService} with the arguments containing the command to be
* sent, with the service calling its
@@ -3468,43 +3465,49 @@
* specify an explicit component name.
* @param conn Receives information as the service is started and stopped.
* This must be a valid ServiceConnection object; it must not be null.
- * @param flags Operation options for the binding. May be 0,
- * {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
- * {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
- * {@link #BIND_ALLOW_OOM_MANAGEMENT}, {@link #BIND_WAIVE_PRIORITY}.
- * {@link #BIND_IMPORTANT}, {@link #BIND_ADJUST_WITH_ACTIVITY},
- * {@link #BIND_NOT_PERCEPTIBLE}, or {@link #BIND_INCLUDE_CAPABILITIES}.
- * @return {@code true} if the system is in the process of bringing up a
- * service that your client has permission to bind to; {@code false}
- * if the system couldn't find the service or if your client doesn't
- * have permission to bind to it. If this value is {@code true}, you
- * should later call {@link #unbindService} to release the
- * connection.
+ * @param flags Operation options for the binding. Can be:
+ * <ul>
+ * <li>0
+ * <li>{@link #BIND_AUTO_CREATE}
+ * <li>{@link #BIND_DEBUG_UNBIND}
+ * <li>{@link #BIND_NOT_FOREGROUND}
+ * <li>{@link #BIND_ABOVE_CLIENT}
+ * <li>{@link #BIND_ALLOW_OOM_MANAGEMENT}
+ * <li>{@link #BIND_WAIVE_PRIORITY}
+ * <li>{@link #BIND_IMPORTANT}
+ * <li>{@link #BIND_ADJUST_WITH_ACTIVITY}
+ * <li>{@link #BIND_NOT_PERCEPTIBLE}
+ * <li>{@link #BIND_INCLUDE_CAPABILITIES}
+ * </ul>
*
- * @throws SecurityException If the caller does not have permission to access the service
- * or the service can not be found.
+ * @return {@code true} if the system is in the process of bringing up a
+ * service that your client has permission to bind to; {@code false}
+ * if the system couldn't find the service or if your client doesn't
+ * have permission to bind to it. Regardless of the return value, you
+ * should later call {@link #unbindService} to release the connection.
+ *
+ * @throws SecurityException If the caller does not have permission to
+ * access the service or the service cannot be found. Call
+ * {@link #unbindService} to release the connection when this exception
+ * is thrown.
*
* @see #unbindService
* @see #startService
- * @see #BIND_AUTO_CREATE
- * @see #BIND_DEBUG_UNBIND
- * @see #BIND_NOT_FOREGROUND
- * @see #BIND_ABOVE_CLIENT
- * @see #BIND_ALLOW_OOM_MANAGEMENT
- * @see #BIND_WAIVE_PRIORITY
- * @see #BIND_IMPORTANT
- * @see #BIND_ADJUST_WITH_ACTIVITY
- * @see #BIND_NOT_PERCEPTIBLE
- * @see #BIND_INCLUDE_CAPABILITIES
*/
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
/**
- * Same as {@link #bindService(Intent, ServiceConnection, int)} with executor to control
- * ServiceConnection callbacks.
+ * Same as {@link #bindService(Intent, ServiceConnection, int)
+ * bindService(Intent, ServiceConnection, int)} with executor to control ServiceConnection
+ * callbacks.
+ *
* @param executor Callbacks on ServiceConnection will be called on executor. Must use same
* instance for the same instance of ServiceConnection.
+ *
+ * @return The result of the binding as described in
+ * {@link #bindService(Intent, ServiceConnection, int)
+ * bindService(Intent, ServiceConnection, int)}.
*/
public boolean bindService(@RequiresPermission @NonNull Intent service,
@BindServiceFlags int flags, @NonNull @CallbackExecutor Executor executor,
@@ -3530,12 +3533,13 @@
* @param instanceName Unique identifier for the service instance. Each unique
* name here will result in a different service instance being created. Identifiers
* must only contain ASCII letters, digits, underscores, and periods.
- * @return Returns success of binding as per {@link #bindService}.
* @param executor Callbacks on ServiceConnection will be called on executor.
* Must use same instance for the same instance of ServiceConnection.
* @param conn Receives information as the service is started and stopped.
* This must be a valid ServiceConnection object; it must not be null.
*
+ * @return Returns success of binding as per {@link #bindService}.
+ *
* @throws SecurityException If the caller does not have permission to access the service
* @throws IllegalArgumentException If the instanceName is invalid.
*
@@ -3550,8 +3554,7 @@
}
/**
- * Binds to a service in the given {@code user} in the same manner as
- * {@link #bindService(Intent, ServiceConnection, int)}.
+ * Binds to a service in the given {@code user} in the same manner as {@link #bindService}.
*
* <p>If the given {@code user} is in the same profile group and the target package is the
* same as the caller, {@code android.Manifest.permission.INTERACT_ACROSS_PROFILES} is
@@ -5778,6 +5781,17 @@
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/ServiceConnection.java b/core/java/android/content/ServiceConnection.java
index 21398f6..660a7f0 100644
--- a/core/java/android/content/ServiceConnection.java
+++ b/core/java/android/content/ServiceConnection.java
@@ -63,8 +63,12 @@
* happen, for example, if the application hosting the service it is bound to
* has been updated.
*
- * @param name The concrete component name of the service whose
- * connection is dead.
+ * <p class="note"><b>Note:</b> The app that requested the binding must call
+ * {@link Context#unbindService(ServiceConnection)} to release the tracking
+ * resources associated with this ServiceConnection even if this callback was
+ * invoked following {@link Context#bindService Context.bindService() bindService()}.
+ *
+ * @param name The concrete component name of the service whose connection is dead.
*/
default void onBindingDied(ComponentName name) {
}
@@ -72,10 +76,10 @@
/**
* Called when the service being bound has returned {@code null} from its
* {@link android.app.Service#onBind(Intent) onBind()} method. This indicates
- * that the attempting service binding represented by this ServiceConnection
+ * that the attempted service binding represented by this ServiceConnection
* will never become usable.
*
- * <p class="note">The app which requested the binding must still call
+ * <p class="note"><b>Note:</b> The app that requested the binding must still call
* {@link Context#unbindService(ServiceConnection)} to release the tracking
* resources associated with this ServiceConnection even if this callback was
* invoked following {@link Context#bindService Context.bindService() bindService()}.
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 4143bfc..ce5cf67 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/SensorManager.java b/core/java/android/hardware/SensorManager.java
index e3ff089..ee62170 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -638,7 +638,7 @@
/**
* Unregisters a listener for the sensors with which it is registered.
*
- * <p class="note"></p>
+ * <p class="note">
* Note: Don't use this method with a one shot trigger sensor such as
* {@link Sensor#TYPE_SIGNIFICANT_MOTION}.
* Use {@link #cancelTriggerSensor(TriggerEventListener, Sensor)} instead.
diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java
index 0c21746..066de11 100644
--- a/core/java/android/hardware/hdmi/HdmiClient.java
+++ b/core/java/android/hardware/hdmi/HdmiClient.java
@@ -17,6 +17,8 @@
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 @@
}
/**
- * 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 @@
}
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 9a9e945..45b0689 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -221,8 +221,8 @@
}
@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 @@
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 7f0e53e..48177e1 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -76,7 +76,7 @@
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 f4db3c3..0000000
--- 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 82ba156..0000000
--- 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 271efe4..070efa3 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -38,7 +38,7 @@
/** 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 036607b..0fd3e03 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -159,8 +159,9 @@
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");
@@ -181,7 +182,7 @@
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;
@@ -238,7 +239,7 @@
* 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.
@@ -400,7 +401,9 @@
mIsBypassable,
mIsMetered,
mMaxMtu,
- mIsRestrictedToTestNetworks);
+ mIsRestrictedToTestNetworks,
+ mExcludeLocalRoutes,
+ mRequiresInternetValidation);
}
@Override
@@ -425,7 +428,8 @@
&& mIsMetered == other.mIsMetered
&& mMaxMtu == other.mMaxMtu
&& mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
- && mExcludeLocalRoutes == other.mExcludeLocalRoutes;
+ && mExcludeLocalRoutes == other.mExcludeLocalRoutes
+ && mRequiresInternetValidation == other.mRequiresInternetValidation;
}
/**
@@ -439,7 +443,7 @@
@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;
@@ -543,7 +547,9 @@
if (profile.excludeLocalRoutes && !profile.isBypassable) {
Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
}
- builder.setExcludeLocalRoutes(profile.excludeLocalRoutes && profile.isBypassable);
+
+ builder.setLocalRoutesExcluded(profile.excludeLocalRoutes && profile.isBypassable);
+ builder.setRequiresInternetValidation(profile.requiresInternetValidation);
return builder.build();
}
@@ -776,6 +782,7 @@
@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;
@@ -988,6 +995,30 @@
}
/**
+ * 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
@@ -1074,7 +1105,7 @@
*/
@NonNull
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
- public Builder setExcludeLocalRoutes(boolean excludeLocalRoutes) {
+ public Builder setLocalRoutesExcluded(boolean excludeLocalRoutes) {
mExcludeLocalRoutes = excludeLocalRoutes;
return this;
}
@@ -1103,7 +1134,8 @@
mIsMetered,
mMaxMtu,
mIsRestrictedToTestNetworks,
- mExcludeLocalRoutes);
+ mExcludeLocalRoutes,
+ mRequiresInternetValidation);
}
}
}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index ab1f542..4b35b0d 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -338,7 +338,9 @@
out.writeInt(TEMPLATE_BACKUP_VERSION_LATEST);
out.writeInt(template.getMatchRule());
- BackupUtils.writeString(out, template.getSubscriberIds().iterator().next());
+ final Set<String> subscriberIds = template.getSubscriberIds();
+ BackupUtils.writeString(out, subscriberIds.isEmpty()
+ ? null : subscriberIds.iterator().next());
BackupUtils.writeString(out, template.getWifiNetworkKeys().isEmpty()
? null : template.getWifiNetworkKeys().iterator().next());
out.writeInt(template.getMeteredness());
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index c936bfa..0e39f42 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -167,6 +167,8 @@
public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
/** @hide */
public static final String FIREWALL_CHAIN_NAME_RESTRICTED = "restricted";
+ /** @hide */
+ public static final String FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY = "low_power_standby";
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
diff --git a/core/java/android/net/PlatformVpnProfile.java b/core/java/android/net/PlatformVpnProfile.java
index 3c45799..6b6f1ca 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 @@
/** @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,12 +80,28 @@
return mType;
}
+ /**
+ * Returns whether the local traffic is exempted from the VPN.
+ */
+ public final boolean areLocalRoutesExcluded() {
+ return mExcludeLocalRoutes;
+ }
/**
- * Returns if the local traffic is exempted from the VPN.
+ * 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 getExcludeLocalRoutes() {
- return mExcludeLocalRoutes;
+ public final boolean isInternetValidationRequired() {
+ return mRequiresInternetValidation;
}
/** Returns a type string describing the VPN profile type */
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index 3193826..c51444c 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -24,6 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -52,7 +53,7 @@
* app (unlike VpnService).
*
* <p>VPN apps using supported protocols should preferentially use this API over the {@link
- * VpnService} API for ease-of-development and reduced maintainance burden. This also give the user
+ * VpnService} API for ease-of-development and reduced maintenance burden. This also give the user
* the guarantee that VPN network traffic is not subjected to on-device packet interception.
*
* @see Ikev2VpnProfile
@@ -97,139 +98,175 @@
public static final String NOTIFICATION_CHANNEL_VPN = "VPN";
/**
- * Action sent in the intent when an error occurred.
+ * Action sent in {@link android.content.Intent}s to VpnManager clients when an event occurred.
*
- * @hide
+ * This action will have a category of either {@link #CATEGORY_EVENT_IKE_ERROR},
+ * {@link #CATEGORY_EVENT_NETWORK_ERROR}, or {@link #CATEGORY_EVENT_DEACTIVATED_BY_USER},
+ * that the app can use to filter events it's interested in reacting to.
+ *
+ * It will also contain the following extras :
+ * <ul>
+ * <li>{@link #EXTRA_SESSION_KEY}, a {@code String} for the session key, as returned by
+ * {@link #startProvisionedVpnProfileSession}.
+ * <li>{@link #EXTRA_TIMESTAMP_MILLIS}, a long for the timestamp at which the error occurred,
+ * in milliseconds since the epoch, as returned by
+ * {@link java.lang.System#currentTimeMillis}.
+ * <li>{@link #EXTRA_UNDERLYING_NETWORK}, a {@link Network} containing the underlying
+ * network at the time the error occurred, or null if none. Note that this network
+ * may have disconnected already.
+ * <li>{@link #EXTRA_UNDERLYING_NETWORK_CAPABILITIES}, a {@link NetworkCapabilities} for
+ * the underlying network at the time the error occurred.
+ * <li>{@link #EXTRA_UNDERLYING_LINK_PROPERTIES}, a {@link LinkProperties} for the underlying
+ * network at the time the error occurred.
+ * </ul>
+ * When this event is an error, either {@link #CATEGORY_EVENT_IKE_ERROR} or
+ * {@link #CATEGORY_EVENT_NETWORK_ERROR}, the following extras will be populated :
+ * <ul>
+ * <li>{@link #EXTRA_ERROR_CLASS}, an {@code int} for the class of error, either
+ * {@link #ERROR_CLASS_RECOVERABLE} or {@link #ERROR_CLASS_NOT_RECOVERABLE}.
+ * <li>{@link #EXTRA_ERROR_CODE}, an {@code int} error code specific to the error. See
+ * {@link #EXTRA_ERROR_CODE} for details.
+ * </ul>
*/
- public static final String ACTION_VPN_MANAGER_ERROR = "android.net.action.VPN_MANAGER_ERROR";
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
/**
- * An IKE protocol error. Codes are the codes from IkeProtocolException, RFC 7296.
+ * An IKE protocol error occurred.
*
- * @hide
+ * Codes (in {@link #EXTRA_ERROR_CODE}) are the codes from
+ * {@link android.net.ipsec.ike.exceptions.IkeProtocolException}, as defined by IANA in
+ * "IKEv2 Notify Message Types - Error Types".
*/
- public static final String CATEGORY_ERROR_IKE = "android.net.category.ERROR_IKE";
+ @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
/**
- * User deactivated the VPN, either by turning it off or selecting a different VPN provider.
- * The error code is always 0.
+ * A network error occurred.
*
- * @hide
+ * Error codes (in {@link #EXTRA_ERROR_CODE}) are ERROR_CODE_NETWORK_*.
*/
- public static final String CATEGORY_ERROR_USER_DEACTIVATED =
- "android.net.category.ERROR_USER_DEACTIVATED";
+ @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_EVENT_NETWORK_ERROR =
+ "android.net.category.EVENT_NETWORK_ERROR";
/**
- * Network error. Error codes are ERROR_CODE_NETWORK_*.
+ * The user deactivated the VPN.
*
- * @hide
+ * This can happen either when the user turns the VPN off explicitly, or when they select
+ * a different VPN provider.
*/
- public static final String CATEGORY_ERROR_NETWORK = "android.net.category.ERROR_NETWORK";
+ @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER =
+ "android.net.category.EVENT_DEACTIVATED_BY_USER";
/**
- * The key of the session that experienced this error, as returned by
- * startProvisionedVpnProfileSession.
+ * The key of the session that experienced this event, as a {@code String}.
*
- * @hide
+ * This is the same key that was returned by {@link #startProvisionedVpnProfileSession}.
*/
public static final String EXTRA_SESSION_KEY = "android.net.extra.SESSION_KEY";
/**
- * Extra for the Network object that was the underlying network at the time of the failure, or
- * null if none.
+ * The network that was underlying the VPN when the event occurred, as a {@link Network}.
*
- * @hide
+ * This extra will be null if there was no underlying network at the time of the event.
*/
public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
/**
- * The NetworkCapabilities of the underlying network.
+ * The {@link NetworkCapabilities} of the underlying network when the event occurred.
*
- * @hide
+ * This extra will be null if there was no underlying network at the time of the event.
*/
public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES =
"android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
/**
- * The LinkProperties of the underlying network.
+ * The {@link LinkProperties} of the underlying network when the event occurred.
*
- * @hide
+ * This extra will be null if there was no underlying network at the time of the event.
*/
public static final String EXTRA_UNDERLYING_LINK_PROPERTIES =
"android.net.extra.UNDERLYING_LINK_PROPERTIES";
/**
- * A long timestamp with SystemClock.elapsedRealtime base for when the event happened.
+ * A {@code long} timestamp containing the time at which the event occurred.
*
- * @hide
+ * This is a number of milliseconds since the epoch, suitable to be compared with
+ * {@link java.lang.System#currentTimeMillis}.
*/
- public static final String EXTRA_TIMESTAMP = "android.net.extra.TIMESTAMP";
+ public static final String EXTRA_TIMESTAMP_MILLIS = "android.net.extra.TIMESTAMP_MILLIS";
/**
- * Extra for the error type. This is ERROR_NOT_RECOVERABLE or ERROR_RECOVERABLE.
+ * Extra for the error class, as an {@code int}.
*
- * @hide
+ * This is always either {@link #ERROR_CLASS_NOT_RECOVERABLE} or
+ * {@link #ERROR_CLASS_RECOVERABLE}. This extra is only populated for error categories.
*/
- public static final String EXTRA_ERROR_TYPE = "android.net.extra.ERROR_TYPE";
+ public static final String EXTRA_ERROR_CLASS = "android.net.extra.ERROR_CLASS";
/**
- * Extra for the error code. The value will be 0 for CATEGORY_ERROR_USER_DEACTIVATED, one of
- * ERROR_CODE_NETWORK_* for ERROR_CATEGORY_NETWORK or one of values defined in
- * IkeProtocolException#ErrorType for CATEGORY_ERROR_IKE.
+ * Extra for an error code, as an {@code int}.
*
- * @hide
+ * <ul>
+ * <li>For {@link #CATEGORY_EVENT_NETWORK_ERROR}, this is one of the
+ * {@code ERROR_CODE_NETWORK_*} constants.
+ * <li>For {@link #CATEGORY_EVENT_IKE_ERROR}, this is one of values defined in
+ * {@link android.net.ipsec.ike.exceptions.IkeProtocolException}.ERROR_TYPE_*.
+ * </ul>
+ * For non-error categories, this extra is not populated.
*/
public static final String EXTRA_ERROR_CODE = "android.net.extra.ERROR_CODE";
/**
- * This error is fatal, e.g. the VPN was disabled or configuration error. The stack will not
- * retry connection.
+ * {@link #EXTRA_ERROR_CLASS} coding for a non-recoverable error.
*
- * @hide
+ * This error is fatal, e.g. configuration error. The stack will not retry connection.
*/
- public static final int ERROR_NOT_RECOVERABLE = 1;
+ public static final int ERROR_CLASS_NOT_RECOVERABLE = 1;
/**
+ * {@link #EXTRA_ERROR_CLASS} coding for a recoverable error.
+ *
* The stack experienced an error but will retry with exponential backoff, e.g. network timeout.
- *
- * @hide
*/
- public static final int ERROR_RECOVERABLE = 2;
+ public static final int ERROR_CLASS_RECOVERABLE = 2;
/**
- * An error code to indicate that there was an UnknownHostException.
+ * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} to indicate that the
+ * network host isn't known.
*
- * @hide
+ * This happens when domain name resolution could not resolve an IP address for the
+ * specified host. {@see java.net.UnknownHostException}
*/
public static final int ERROR_CODE_NETWORK_UNKNOWN_HOST = 0;
/**
- * An error code to indicate that there is a SocketTimeoutException.
+ * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating a timeout.
*
- * @hide
+ * For Ikev2 VPNs, this happens typically after a retransmission failure.
+ * {@see android.net.ipsec.ike.exceptions.IkeTimeoutException}
*/
- public static final int ERROR_CODE_NETWORK_TIMEOUT = 1;
+ public static final int ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT = 1;
/**
- * An error code to indicate that the connection is refused.
+ * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating that
+ * network connectivity was lost.
*
- * @hide
+ * The most common reason for this error is that the underlying network was disconnected,
+ * {@see android.net.ipsec.ike.exceptions.IkeNetworkLostException}.
*/
- public static final int ERROR_CODE_NETWORK_CONNECT = 2;
+ public static final int ERROR_CODE_NETWORK_LOST = 2;
/**
- * An error code to indicate the connection was reset. (e.g. SocketException)
+ * An {@link #EXTRA_ERROR_CODE} for {@link #CATEGORY_EVENT_NETWORK_ERROR} indicating an
+ * input/output error.
*
- * @hide
+ * This code happens when reading or writing to sockets on the underlying networks was
+ * terminated by an I/O error. {@see IOException}.
*/
- public static final int ERROR_CODE_NETWORK_CONNECTION_RESET = 3;
-
- /**
- * 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 +354,32 @@
/**
* 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
index 9772bde..2dd3aaa1 100644
--- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -24,6 +24,7 @@
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.NonNull;
import android.annotation.SystemApi;
@@ -108,6 +109,7 @@
static final int VERSION_ADD_METERED = 4;
static final int VERSION_ADD_DEFAULT_NETWORK = 5;
static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
+ static final int VERSION_ADD_SUB_ID = 7;
}
/**
@@ -448,6 +450,13 @@
oemNetCapabilities = NetworkTemplate.OEM_MANAGED_NO;
}
+ final int subId;
+ if (version >= IdentitySetVersion.VERSION_ADD_SUB_ID) {
+ subId = in.readInt();
+ } else {
+ subId = INVALID_SUBSCRIPTION_ID;
+ }
+
// 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);
@@ -457,7 +466,8 @@
.setWifiNetworkKey(networkId)
.setRoaming(roaming).setMetered(metered)
.setDefaultNetwork(defaultNetwork)
- .setOemManaged(oemNetCapabilities);
+ .setOemManaged(oemNetCapabilities)
+ .setSubId(subId);
if (type == TYPE_MOBILE && ratType != NetworkTemplate.NETWORK_TYPE_ALL) {
builder.setRatType(ratType);
}
@@ -501,10 +511,10 @@
* 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.
+ * @param taggedData whether to read only tagged data (true) or only non-tagged data
+ * (false). 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
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 0a9fe90..2b34d86 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -25,6 +25,7 @@
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.nfc.INfcCardEmulation;
@@ -62,7 +63,9 @@
* replace the current default service with the service
* identified with the ComponentName specified in
* {@link #EXTRA_SERVICE_COMPONENT}, for the category
- * specified in {@link #EXTRA_CATEGORY}
+ * specified in {@link #EXTRA_CATEGORY}. There is an optional
+ * extra field using {@link Intent#EXTRA_USER} to specify
+ * the {@link UserHandle} of the user that owns the app.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_CHANGE_DEFAULT =
@@ -84,13 +87,6 @@
public static final String EXTRA_SERVICE_COMPONENT = "component";
/**
- * The caller userId extra for {@link #ACTION_CHANGE_DEFAULT}.
- *
- * @see #ACTION_CHANGE_DEFAULT
- */
- public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
-
- /**
* Category used for NFC payment services.
*/
public static final String CATEGORY_PAYMENT = "payment";
diff --git a/core/java/android/os/BadTypeParcelableException.java b/core/java/android/os/BadTypeParcelableException.java
new file mode 100644
index 0000000..2ca3bd2
--- /dev/null
+++ b/core/java/android/os/BadTypeParcelableException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.os;
+
+/** Used by Parcel to signal that the type on the payload was not expected by the caller. */
+class BadTypeParcelableException extends BadParcelableException {
+ BadTypeParcelableException(String msg) {
+ super(msg);
+ }
+ BadTypeParcelableException(Exception cause) {
+ super(cause);
+ }
+ BadTypeParcelableException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index ad3de25..e5dab05 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -16,6 +16,8 @@
package android.os;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -31,7 +33,7 @@
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Set;
-import java.util.function.Supplier;
+import java.util.function.BiFunction;
/**
* A mapping from String keys to values of various types. In most cases, you
@@ -252,11 +254,10 @@
if (size == 0) {
return null;
}
- Object o = getValueAt(0);
try {
- return (String) o;
- } catch (ClassCastException e) {
- typeWarning("getPairValue()", o, "String", e);
+ return getValueAt(0, String.class);
+ } catch (ClassCastException | BadTypeParcelableException e) {
+ typeWarning("getPairValue()", "String", e);
return null;
}
}
@@ -309,7 +310,7 @@
}
for (int i = 0, n = mMap.size(); i < n; i++) {
// Triggers deserialization of i-th item, if needed
- getValueAt(i);
+ getValueAt(i, /* clazz */ null);
}
}
}
@@ -321,26 +322,59 @@
* This call should always be made after {@link #unparcel()} or inside a lock after making sure
* {@code mMap} is not null.
*
+ * @deprecated Use {@link #getValue(String, Class, Class[])}. This method should only be used in
+ * other deprecated APIs.
+ *
* @hide
*/
+ @Deprecated
+ @Nullable
final Object getValue(String key) {
- int i = mMap.indexOfKey(key);
- return (i >= 0) ? getValueAt(i) : null;
+ return getValue(key, /* clazz */ null);
+ }
+
+ /** Same as {@link #getValue(String, Class, Class[])} with no item types. */
+ @Nullable
+ final <T> T getValue(String key, @Nullable Class<T> clazz) {
+ // Avoids allocating Class[0] array
+ return getValue(key, clazz, (Class<?>[]) null);
}
/**
- * Returns the value for a certain position in the array map.
+ * Returns the value for key {@code key} for expected return type {@code clazz} (or pass {@code
+ * null} for no type check).
+ *
+ * For {@code itemTypes}, see {@link Parcel#readValue(int, ClassLoader, Class, Class[])}.
*
* This call should always be made after {@link #unparcel()} or inside a lock after making sure
* {@code mMap} is not null.
*
* @hide
*/
- final Object getValueAt(int i) {
+ @Nullable
+ final <T> T getValue(String key, @Nullable Class<T> clazz, @Nullable Class<?>... itemTypes) {
+ int i = mMap.indexOfKey(key);
+ return (i >= 0) ? getValueAt(i, clazz, itemTypes) : null;
+ }
+
+ /**
+ * Returns the value for a certain position in the array map for expected return type {@code
+ * clazz} (or pass {@code null} for no type check).
+ *
+ * For {@code itemTypes}, see {@link Parcel#readValue(int, ClassLoader, Class, Class[])}.
+ *
+ * This call should always be made after {@link #unparcel()} or inside a lock after making sure
+ * {@code mMap} is not null.
+ *
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Nullable
+ final <T> T getValueAt(int i, @Nullable Class<T> clazz, @Nullable Class<?>... itemTypes) {
Object object = mMap.valueAt(i);
- if (object instanceof Supplier<?>) {
+ if (object instanceof BiFunction<?, ?, ?>) {
try {
- object = ((Supplier<?>) object).get();
+ object = ((BiFunction<Class<?>, Class<?>[], ?>) object).apply(clazz, itemTypes);
} catch (BadParcelableException e) {
if (sShouldDefuse) {
Log.w(TAG, "Failed to parse item " + mMap.keyAt(i) + ", returning null.", e);
@@ -351,7 +385,7 @@
}
mMap.setValueAt(i, object);
}
- return object;
+ return (clazz != null) ? clazz.cast(object) : (T) object;
}
private void initializeFromParcelLocked(@NonNull Parcel parcelledData, boolean recycleParcel,
@@ -528,7 +562,7 @@
} else {
// Following semantic above of failing in case we get a serialized value vs a
// deserialized one, we'll compare the map. If a certain element hasn't been
- // deserialized yet, it's a Supplier (or more specifically a LazyValue, but let's
+ // deserialized yet, it's a function object (or more specifically a LazyValue, but let's
// pretend we don't know that here :P), we'll use that element's equality comparison as
// map naturally does. That will takes care of comparing the payload if needed (see
// Parcel.readLazyValue() for details).
@@ -602,7 +636,11 @@
*
* @param key a String key
* @return an Object, or null
+ *
+ * @deprecated Use the type-safe specific APIs depending on the type of the item to be
+ * retrieved, eg. {@link #getString(String)}.
*/
+ @Deprecated
@Nullable
public Object get(String key) {
unparcel();
@@ -610,6 +648,32 @@
}
/**
+ * Returns the object of type {@code clazz} for the given {@code key}, or {@code null} if:
+ * <ul>
+ * <li>No mapping of the desired type exists for the given key.
+ * <li>A {@code null} value is explicitly associated with the key.
+ * <li>The object is not of type {@code clazz}.
+ * </ul>
+ *
+ * <p>Use the more specific APIs where possible, especially in the case of containers such as
+ * lists, since those APIs allow you to specify the type of the items.
+ *
+ * @param key String key
+ * @param clazz The type of the object expected
+ * @return an Object, or null
+ */
+ @Nullable
+ <T> T get(@Nullable String key, @NonNull Class<T> clazz) {
+ unparcel();
+ try {
+ return getValue(key, requireNonNull(clazz));
+ } catch (ClassCastException | BadTypeParcelableException e) {
+ typeWarning(key, clazz.getCanonicalName(), e);
+ return null;
+ }
+ }
+
+ /**
* Removes any entry with the given key from the mapping of this Bundle.
*
* @param key a String key
@@ -982,15 +1046,19 @@
}
// Log a message if the value was non-null but not of the expected type
- void typeWarning(String key, Object value, String className,
- Object defaultValue, ClassCastException e) {
+ void typeWarning(String key, @Nullable Object value, String className,
+ Object defaultValue, RuntimeException e) {
StringBuilder sb = new StringBuilder();
sb.append("Key ");
sb.append(key);
sb.append(" expected ");
sb.append(className);
- sb.append(" but value was a ");
- sb.append(value.getClass().getName());
+ if (value != null) {
+ sb.append(" but value was a ");
+ sb.append(value.getClass().getName());
+ } else {
+ sb.append(" but value was of a different type");
+ }
sb.append(". The default value ");
sb.append(defaultValue);
sb.append(" was returned.");
@@ -998,11 +1066,14 @@
Log.w(TAG, "Attempt to cast generated internal exception:", e);
}
- void typeWarning(String key, Object value, String className,
- ClassCastException e) {
+ void typeWarning(String key, @Nullable Object value, String className, RuntimeException e) {
typeWarning(key, value, className, "<null>", e);
}
+ void typeWarning(String key, String className, RuntimeException e) {
+ typeWarning(key, /* value */ null, className, "<null>", e);
+ }
+
/**
* Returns the value associated with the given key, or defaultValue if
* no mapping of the desired type exists for the given key.
@@ -1342,7 +1413,11 @@
*
* @param key a String, or null
* @return a Serializable value, or null
+ *
+ * @deprecated Use {@link #getSerializable(String, Class)}. This method should only be used in
+ * other deprecated APIs.
*/
+ @Deprecated
@Nullable
Serializable getSerializable(@Nullable String key) {
unparcel();
@@ -1359,6 +1434,36 @@
}
/**
+ * Returns the value associated with the given key, or {@code null} if:
+ * <ul>
+ * <li>No mapping of the desired type exists for the given key.
+ * <li>A {@code null} value is explicitly associated with the key.
+ * <li>The object is not of type {@code clazz}.
+ * </ul>
+ *
+ * @param key a String, or null
+ * @param clazz The expected class of the returned type
+ * @return a Serializable value, or null
+ */
+ @Nullable
+ <T extends Serializable> T getSerializable(@Nullable String key, @NonNull Class<T> clazz) {
+ return get(key, clazz);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ <T> ArrayList<T> getArrayList(@Nullable String key, @NonNull Class<? extends T> clazz) {
+ unparcel();
+ try {
+ return getValue(key, ArrayList.class, requireNonNull(clazz));
+ } catch (ClassCastException | BadTypeParcelableException e) {
+ typeWarning(key, "ArrayList<" + clazz.getCanonicalName() + ">", e);
+ return null;
+ }
+ }
+
+ /**
* Returns the value associated with the given key, or null if
* no mapping of the desired type exists for the given key or a null
* value is explicitly associated with the key.
@@ -1368,17 +1473,7 @@
*/
@Nullable
ArrayList<Integer> getIntegerArrayList(@Nullable String key) {
- unparcel();
- Object o = getValue(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<Integer>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<Integer>", e);
- return null;
- }
+ return getArrayList(key, Integer.class);
}
/**
@@ -1391,17 +1486,7 @@
*/
@Nullable
ArrayList<String> getStringArrayList(@Nullable String key) {
- unparcel();
- Object o = getValue(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<String>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<String>", e);
- return null;
- }
+ return getArrayList(key, String.class);
}
/**
@@ -1414,17 +1499,7 @@
*/
@Nullable
ArrayList<CharSequence> getCharSequenceArrayList(@Nullable String key) {
- unparcel();
- Object o = getValue(key);
- if (o == null) {
- return null;
- }
- try {
- return (ArrayList<CharSequence>) o;
- } catch (ClassCastException e) {
- typeWarning(key, o, "ArrayList<CharSequence>", e);
- return null;
- }
+ return getArrayList(key, CharSequence.class);
}
/**
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 2a2cbb9..71c63ff 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -516,12 +516,15 @@
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 @@
}
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 e519ff3..03492aa 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -31,6 +31,7 @@
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 java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -283,13 +285,20 @@
public static final String RELEASE = getString("ro.build.version.release");
/**
- * The version string we show to the user; may be {@link #RELEASE} or
- * {@link #CODENAME} if not a final release build.
+ * The version string. May be {@link #RELEASE} or {@link #CODENAME} if
+ * not a final release build.
*/
@NonNull public static final String RELEASE_OR_CODENAME = getString(
"ro.build.version.release_or_codename");
/**
+ * The version string we show to the user; may be {@link #RELEASE} or
+ * a descriptive string if not a final release build.
+ */
+ @NonNull public static final String RELEASE_OR_PREVIEW_DISPLAY = getString(
+ "ro.build.version.release_or_preview_display");
+
+ /**
* The base OS build the product is based on.
*/
public static final String BASE_OS = SystemProperties.get("ro.build.version.base_os", "");
@@ -396,6 +405,22 @@
*/
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, i.e. if {@link #CODENAME} is not "REL"
+ * then the value of that is present in this set.
+ *
+ * <p>If a particular string is not present in this set, then it is either not a codename
+ * or a codename for a future release. For example, during Android R development, "Tiramisu"
+ * was not a known codename.
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull public static final Set<String> KNOWN_CODENAMES =
+ new ArraySet<>(getStringList("ro.build.version.known_codenames", ","));
+
private static final String[] ALL_CODENAMES
= getStringList("ro.build.version.all_codenames", ",");
@@ -1024,7 +1049,7 @@
* 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 +1157,14 @@
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/Bundle.java b/core/java/android/os/Bundle.java
index b2bbfd6..a19b51b 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -16,7 +16,11 @@
package android.os;
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.ArrayMap;
import android.util.Size;
@@ -873,7 +877,7 @@
@Nullable
public Bundle getBundle(@Nullable String key) {
unparcel();
- Object o = getValue(key);
+ Object o = mMap.get(key);
if (o == null) {
return null;
}
@@ -896,7 +900,11 @@
*
* @param key a String, or {@code null}
* @return a Parcelable value, or {@code null}
+ *
+ * @deprecated Use the type-safer {@link #getParcelable(String, Class)} starting from Android
+ * {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Nullable
public <T extends Parcelable> T getParcelable(@Nullable String key) {
unparcel();
@@ -913,6 +921,31 @@
}
/**
+ * Returns the value associated with the given key or {@code null} if:
+ * <ul>
+ * <li>No mapping of the desired type exists for the given key.
+ * <li>A {@code null} value is explicitly associated with the key.
+ * <li>The object is not of type {@code clazz}.
+ * </ul>
+ *
+ * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+ * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+ * Otherwise, this method might throw an exception or return {@code null}.
+ *
+ * @param key a String, or {@code null}
+ * @param clazz The type of the object expected
+ * @return a Parcelable value, or {@code null}
+ */
+ @SuppressWarnings("unchecked")
+ @Nullable
+ public <T> T getParcelable(@Nullable String key, @NonNull Class<T> clazz) {
+ // The reason for not using <T extends Parcelable> is because the caller could provide a
+ // super class to restrict the children that doesn't implement Parcelable itself while the
+ // children do, more details at b/210800751 (same reasoning applies here).
+ return get(key, clazz);
+ }
+
+ /**
* Returns the value associated with the given key, or {@code null} if
* no mapping of the desired type exists for the given key or a null
* value is explicitly associated with the key.
@@ -923,7 +956,11 @@
*
* @param key a String, or {@code null}
* @return a Parcelable[] value, or {@code null}
+ *
+ * @deprecated Use the type-safer {@link #getParcelableArray(String, Class)} starting from
+ * Android {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Nullable
public Parcelable[] getParcelableArray(@Nullable String key) {
unparcel();
@@ -940,6 +977,39 @@
}
/**
+ * Returns the value associated with the given key, or {@code null} if:
+ * <ul>
+ * <li>No mapping of the desired type exists for the given key.
+ * <li>A {@code null} value is explicitly associated with the key.
+ * <li>The object is not of type {@code clazz}.
+ * </ul>
+ *
+ * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+ * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+ * Otherwise, this method might throw an exception or return {@code null}.
+ *
+ * @param key a String, or {@code null}
+ * @param clazz The type of the items inside the array
+ * @return a Parcelable[] value, or {@code null}
+ */
+ @SuppressLint({"ArrayReturn", "NullableCollection"})
+ @SuppressWarnings("unchecked")
+ @Nullable
+ public <T> T[] getParcelableArray(@Nullable String key, @NonNull Class<T> clazz) {
+ // The reason for not using <T extends Parcelable> is because the caller could provide a
+ // super class to restrict the children that doesn't implement Parcelable itself while the
+ // children do, more details at b/210800751 (same reasoning applies here).
+ unparcel();
+ try {
+ // In Java 12, we can pass clazz.arrayType() instead of Parcelable[] and later casting.
+ return (T[]) getValue(key, Parcelable[].class, requireNonNull(clazz));
+ } catch (ClassCastException | BadTypeParcelableException e) {
+ typeWarning(key, clazz.getCanonicalName() + "[]", e);
+ return null;
+ }
+ }
+
+ /**
* Returns the value associated with the given key, or {@code null} if
* no mapping of the desired type exists for the given key or a {@code null}
* value is explicitly associated with the key.
@@ -950,7 +1020,11 @@
*
* @param key a String, or {@code null}
* @return an ArrayList<T> value, or {@code null}
+ *
+ * @deprecated Use the type-safer {@link #getParcelable(String, Class)} starting from Android
+ * {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Nullable
public <T extends Parcelable> ArrayList<T> getParcelableArrayList(@Nullable String key) {
unparcel();
@@ -967,14 +1041,44 @@
}
/**
+ * Returns the value associated with the given key, or {@code null} if:
+ * <ul>
+ * <li>No mapping of the desired type exists for the given key.
+ * <li>A {@code null} value is explicitly associated with the key.
+ * <li>The object is not of type {@code clazz}.
+ * </ul>
+ *
+ * <p><b>Note: </b> if the expected value is not a class provided by the Android platform,
+ * you must call {@link #setClassLoader(ClassLoader)} with the proper {@link ClassLoader} first.
+ * Otherwise, this method might throw an exception or return {@code null}.
+ *
+ * @param key a String, or {@code null}
+ * @param clazz The type of the items inside the array list
+ * @return an ArrayList<T> value, or {@code null}
+ */
+ @SuppressLint("NullableCollection")
+ @SuppressWarnings("unchecked")
+ @Nullable
+ public <T> ArrayList<T> getParcelableArrayList(@Nullable String key,
+ @NonNull Class<? extends T> clazz) {
+ // The reason for not using <T extends Parcelable> is because the caller could provide a
+ // super class to restrict the children that doesn't implement Parcelable itself while the
+ // children do, more details at b/210800751 (same reasoning applies here).
+ return getArrayList(key, clazz);
+ }
+
+ /**
* Returns the value associated with the given key, or null if
* no mapping of the desired type exists for the given key or a null
* value is explicitly associated with the key.
*
* @param key a String, or null
- *
* @return a SparseArray of T values, or null
+ *
+ * @deprecated Use the type-safer {@link #getSparseParcelableArray(String, Class)} starting from
+ * Android {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Nullable
public <T extends Parcelable> SparseArray<T> getSparseParcelableArray(@Nullable String key) {
unparcel();
@@ -991,13 +1095,44 @@
}
/**
+ * Returns the value associated with the given key, or {@code null} if:
+ * <ul>
+ * <li>No mapping of the desired type exists for the given key.
+ * <li>A {@code null} value is explicitly associated with the key.
+ * <li>The object is not of type {@code clazz}.
+ * </ul>
+ *
+ * @param key a String, or null
+ * @return a SparseArray of T values, or null
+ */
+ @SuppressWarnings("unchecked")
+ @Nullable
+ public <T> SparseArray<T> getSparseParcelableArray(@Nullable String key,
+ @NonNull Class<? extends T> clazz) {
+ // The reason for not using <T extends Parcelable> is because the caller could provide a
+ // super class to restrict the children that doesn't implement Parcelable itself while the
+ // children do, more details at b/210800751 (same reasoning applies here).
+ unparcel();
+ try {
+ return (SparseArray<T>) getValue(key, SparseArray.class, requireNonNull(clazz));
+ } catch (ClassCastException | BadTypeParcelableException e) {
+ typeWarning(key, "SparseArray<" + clazz.getCanonicalName() + ">", e);
+ return null;
+ }
+ }
+
+ /**
* Returns the value associated with the given key, or null if
* no mapping of the desired type exists for the given key or a null
* value is explicitly associated with the key.
*
* @param key a String, or null
* @return a Serializable value, or null
+ *
+ * @deprecated Use the type-safer {@link #getSerializable(String, Class)} starting from Android
+ * {@link Build.VERSION_CODES#TIRAMISU}.
*/
+ @Deprecated
@Override
@Nullable
public Serializable getSerializable(@Nullable String key) {
@@ -1005,6 +1140,24 @@
}
/**
+ * Returns the value associated with the given key, or {@code null} if:
+ * <ul>
+ * <li>No mapping of the desired type exists for the given key.
+ * <li>A {@code null} value is explicitly associated with the key.
+ * <li>The object is not of type {@code clazz}.
+ * </ul>
+ *
+ * @param key a String, or null
+ * @param clazz The expected class of the returned type
+ * @return a Serializable value, or null
+ */
+ @Nullable
+ public <T extends Serializable> T getSerializable(@Nullable String key,
+ @NonNull Class<T> clazz) {
+ return super.getSerializable(key, requireNonNull(clazz));
+ }
+
+ /**
* Returns the value associated with the given key, or null if
* no mapping of the desired type exists for the given key or a null
* value is explicitly associated with the key.
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 2ed0bad..2f2f65b 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -101,6 +101,7 @@
private static final File DIR_ANDROID_EXPAND = getDirectory(ENV_ANDROID_EXPAND, "/mnt/expand");
private static final File DIR_ANDROID_STORAGE = getDirectory(ENV_ANDROID_STORAGE, "/storage");
private static final File DIR_DOWNLOAD_CACHE = getDirectory(ENV_DOWNLOAD_CACHE, "/cache");
+ private static final File DIR_METADATA = new File("/metadata");
private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
@@ -1102,6 +1103,15 @@
}
/**
+ * Return the metadata directory.
+ *
+ * @hide
+ */
+ public static @NonNull File getMetadataDirectory() {
+ return DIR_METADATA;
+ }
+
+ /**
* Unknown storage state, such as when a path isn't backed by known storage
* media.
*
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 5d9f2189..8e5ed8f 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -52,6 +52,9 @@
per-file *Telephony* = file:/telephony/OWNERS
per-file *Zygote* = file:/ZYGOTE_OWNERS
+# Time
+per-file *Clock* = file:/services/core/java/com/android/server/timezonedetector/OWNERS
+
# RecoverySystem
per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 09eac79..9b03172 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -16,8 +16,11 @@
package android.os;
+import static com.android.internal.util.Preconditions.checkArgument;
+
import static java.util.Objects.requireNonNull;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -53,6 +56,8 @@
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;
@@ -62,6 +67,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Supplier;
@@ -195,7 +201,7 @@
* The methods to use are {@link #writeFileDescriptor(FileDescriptor)},
* {@link #readFileDescriptor()}.
*
- * <h3>Untyped Containers</h3>
+ * <h3>Parcelable Containers</h3>
*
* <p>A final class of methods are for writing and reading standard Java
* containers of arbitrary types. These all revolve around the
@@ -207,6 +213,19 @@
* {@link #writeMap(Map)}, {@link #readMap(Map, ClassLoader)},
* {@link #writeSparseArray(SparseArray)},
* {@link #readSparseArray(ClassLoader)}.
+ *
+ * <h3>Restricted Parcelable Containers</h3>
+ *
+ * <p>A final class of methods are for reading standard Java containers of restricted types.
+ * These methods replace methods for reading containers of arbitrary types from previous section
+ * starting from Android {@link Build.VERSION_CODES#TIRAMISU}. The pairing writing methods are
+ * still the same from previous section.
+ * These methods accepts additional {@code clazz} parameters as the required types.
+ * The Restricted Parcelable container methods are {@link #readArray(ClassLoader, Class)},
+ * {@link #readList(List, ClassLoader, Class)},
+ * {@link #readArrayList(ClassLoader, Class)},
+ * {@link #readMap(Map, ClassLoader, Class, Class)},
+ * {@link #readSparseArray(ClassLoader, Class)}.
*/
public final class Parcel {
@@ -229,6 +248,25 @@
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.
@@ -265,26 +303,26 @@
private static final int VAL_NULL = -1;
private static final int VAL_STRING = 0;
private static final int VAL_INTEGER = 1;
- private static final int VAL_MAP = 2;
+ private static final int VAL_MAP = 2; // length-prefixed
private static final int VAL_BUNDLE = 3;
- private static final int VAL_PARCELABLE = 4;
+ private static final int VAL_PARCELABLE = 4; // length-prefixed
private static final int VAL_SHORT = 5;
private static final int VAL_LONG = 6;
private static final int VAL_FLOAT = 7;
private static final int VAL_DOUBLE = 8;
private static final int VAL_BOOLEAN = 9;
private static final int VAL_CHARSEQUENCE = 10;
- private static final int VAL_LIST = 11;
- private static final int VAL_SPARSEARRAY = 12;
+ private static final int VAL_LIST = 11; // length-prefixed
+ private static final int VAL_SPARSEARRAY = 12; // length-prefixed
private static final int VAL_BYTEARRAY = 13;
private static final int VAL_STRINGARRAY = 14;
private static final int VAL_IBINDER = 15;
- private static final int VAL_PARCELABLEARRAY = 16;
- private static final int VAL_OBJECTARRAY = 17;
+ private static final int VAL_PARCELABLEARRAY = 16; // length-prefixed
+ private static final int VAL_OBJECTARRAY = 17; // length-prefixed
private static final int VAL_INTARRAY = 18;
private static final int VAL_LONGARRAY = 19;
private static final int VAL_BYTE = 20;
- private static final int VAL_SERIALIZABLE = 21;
+ private static final int VAL_SERIALIZABLE = 21; // length-prefixed
private static final int VAL_SPARSEBOOLEANARRAY = 22;
private static final int VAL_BOOLEANARRAY = 23;
private static final int VAL_CHARSEQUENCEARRAY = 24;
@@ -585,6 +623,40 @@
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 +2151,102 @@
}
/**
+ * 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 +3108,15 @@
* 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;
}
/**
@@ -3010,8 +3186,7 @@
*/
@Deprecated
public final void readMap(@NonNull Map outVal, @Nullable ClassLoader loader) {
- int n = readInt();
- readMapInternal(outVal, n, loader, /* clazzKey */ null, /* clazzValue */ null);
+ readMapInternal(outVal, loader, /* clazzKey */ null, /* clazzValue */ null);
}
/**
@@ -3026,8 +3201,7 @@
@NonNull Class<V> clazzValue) {
Objects.requireNonNull(clazzKey);
Objects.requireNonNull(clazzValue);
- int n = readInt();
- readMapInternal(outVal, n, loader, clazzKey, clazzValue);
+ readMapInternal(outVal, loader, clazzKey, clazzValue);
}
/**
@@ -3076,13 +3250,7 @@
@Deprecated
@Nullable
public HashMap readHashMap(@Nullable ClassLoader loader) {
- int n = readInt();
- if (n < 0) {
- return null;
- }
- HashMap m = new HashMap(n);
- readMapInternal(m, n, loader, /* clazzKey */ null, /* clazzValue */ null);
- return m;
+ return readHashMapInternal(loader, /* clazzKey */ null, /* clazzValue */ null);
}
/**
@@ -3098,13 +3266,7 @@
@NonNull Class<? extends K> clazzKey, @NonNull Class<? extends V> clazzValue) {
Objects.requireNonNull(clazzKey);
Objects.requireNonNull(clazzValue);
- int n = readInt();
- if (n < 0) {
- return null;
- }
- HashMap<K, V> map = new HashMap<>(n);
- readMapInternal(map, n, loader, clazzKey, clazzValue);
- return map;
+ return readHashMapInternal(loader, clazzKey, clazzValue);
}
/**
@@ -3683,7 +3845,7 @@
*/
@NonNull
public <T> List<T> readParcelableList(@NonNull List<T> list,
- @Nullable ClassLoader cl, @NonNull Class<T> clazz) {
+ @Nullable ClassLoader cl, @NonNull Class<? extends T> clazz) {
Objects.requireNonNull(list);
Objects.requireNonNull(clazz);
return readParcelableListInternal(list, cl, clazz);
@@ -3694,7 +3856,7 @@
*/
@NonNull
private <T> List<T> readParcelableListInternal(@NonNull List<T> list,
- @Nullable ClassLoader cl, @Nullable Class<T> clazz) {
+ @Nullable ClassLoader cl, @Nullable Class<? extends T> clazz) {
final int n = readInt();
if (n == -1) {
list.clear();
@@ -3781,6 +3943,317 @@
}
/**
+ * 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
@@ -3818,16 +4291,17 @@
/**
- * @param clazz The type of the object expected or {@code null} for performing no checks.
+ * @see #readValue(int, ClassLoader, Class, Class[])
*/
@Nullable
- private <T> T readValue(@Nullable ClassLoader loader, @Nullable Class<T> clazz) {
+ private <T> T readValue(@Nullable ClassLoader loader, @Nullable Class<T> clazz,
+ @Nullable Class<?>... itemTypes) {
int type = readInt();
final T object;
if (isLengthPrefixed(type)) {
int length = readInt();
int start = dataPosition();
- object = readValue(type, loader, clazz);
+ object = readValue(type, loader, clazz, itemTypes);
int actual = dataPosition() - start;
if (actual != length) {
Slog.wtfStack(TAG,
@@ -3835,24 +4309,26 @@
+ " consumed " + actual + " bytes, but " + length + " expected.");
}
} else {
- object = readValue(type, loader, clazz);
+ object = readValue(type, loader, clazz, itemTypes);
}
return object;
}
/**
- * This will return a {@link Supplier} for length-prefixed types that deserializes the object
- * when {@link Supplier#get()} is called, for other types it will return the object itself.
+ * This will return a {@link BiFunction} for length-prefixed types that deserializes the object
+ * when {@link BiFunction#apply} is called (the arguments correspond to the ones of {@link
+ * #readValue(int, ClassLoader, Class, Class[])} after the class loader), for other types it
+ * will return the object itself.
*
- * <p>After calling {@link Supplier#get()} the parcel cursor will not change. Note that you
+ * <p>After calling {@link BiFunction#apply} the parcel cursor will not change. Note that you
* shouldn't recycle the parcel, not at least until all objects have been retrieved. No
* synchronization attempts are made.
*
- * </p>The supplier returned implements {@link #equals(Object)} and {@link #hashCode()}. Two
- * suppliers are equal if either of the following is true:
+ * </p>The function returned implements {@link #equals(Object)} and {@link #hashCode()}. Two
+ * function objects are equal if either of the following is true:
* <ul>
- * <li>{@link Supplier#get()} has been called on both and both objects returned are equal.
- * <li>{@link Supplier#get()} hasn't been called on either one and everything below is true:
+ * <li>{@link BiFunction#apply} has been called on both and both objects returned are equal.
+ * <li>{@link BiFunction#apply} hasn't been called on either one and everything below is true:
* <ul>
* <li>The {@code loader} parameters used to retrieve each are equal.
* <li>They both have the same type.
@@ -3879,7 +4355,7 @@
}
- private static final class LazyValue implements Supplier<Object> {
+ private static final class LazyValue implements BiFunction<Class<?>, Class<?>[], Object> {
/**
* | 4B | 4B |
* mSource = Parcel{... | type | length | object | ...}
@@ -3911,7 +4387,7 @@
}
@Override
- public Object get() {
+ public Object apply(@Nullable Class<?> clazz, @Nullable Class<?>[] itemTypes) {
Parcel source = mSource;
if (source != null) {
synchronized (source) {
@@ -3920,7 +4396,7 @@
int restore = source.dataPosition();
try {
source.setDataPosition(mPosition);
- mObject = source.readValue(mLoader);
+ mObject = source.readValue(mLoader, clazz, itemTypes);
} finally {
source.setDataPosition(restore);
}
@@ -4000,14 +4476,25 @@
}
}
+ /** Same as {@link #readValue(ClassLoader, Class, Class[])} without any item types. */
+ private <T> T readValue(int type, @Nullable ClassLoader loader, @Nullable Class<T> clazz) {
+ // Avoids allocating Class[0] array
+ return readValue(type, loader, clazz, (Class<?>[]) null);
+ }
+
/**
* Reads a value from the parcel of type {@code type}. Does NOT read the int representing the
* type first.
+ *
* @param clazz The type of the object expected or {@code null} for performing no checks.
+ * @param itemTypes If the value is a container, these represent the item types (eg. for a list
+ * it's the item type, for a map, it's the key type, followed by the value
+ * type).
*/
@SuppressWarnings("unchecked")
@Nullable
- private <T> T readValue(int type, @Nullable ClassLoader loader, @Nullable Class<T> clazz) {
+ private <T> T readValue(int type, @Nullable ClassLoader loader, @Nullable Class<T> clazz,
+ @Nullable Class<?>... itemTypes) {
final Object object;
switch (type) {
case VAL_NULL:
@@ -4023,7 +4510,11 @@
break;
case VAL_MAP:
- object = readHashMap(loader);
+ checkTypeToUnparcel(clazz, HashMap.class);
+ Class<?> keyType = ArrayUtils.getOrNull(itemTypes, 0);
+ Class<?> valueType = ArrayUtils.getOrNull(itemTypes, 1);
+ checkArgument((keyType == null) == (valueType == null));
+ object = readHashMapInternal(loader, keyType, valueType);
break;
case VAL_PARCELABLE:
@@ -4054,10 +4545,12 @@
object = readCharSequence();
break;
- case VAL_LIST:
- object = readArrayList(loader);
+ case VAL_LIST: {
+ checkTypeToUnparcel(clazz, ArrayList.class);
+ Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0);
+ object = readArrayListInternal(loader, itemType);
break;
-
+ }
case VAL_BOOLEANARRAY:
object = createBooleanArray();
break;
@@ -4078,10 +4571,12 @@
object = readStrongBinder();
break;
- case VAL_OBJECTARRAY:
- object = readArray(loader);
+ case VAL_OBJECTARRAY: {
+ Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0);
+ checkArrayTypeToUnparcel(clazz, (itemType != null) ? itemType : Object.class);
+ object = readArrayInternal(loader, itemType);
break;
-
+ }
case VAL_INTARRAY:
object = createIntArray();
break;
@@ -4098,14 +4593,18 @@
object = readSerializableInternal(loader, clazz);
break;
- case VAL_PARCELABLEARRAY:
- object = readParcelableArray(loader);
+ case VAL_PARCELABLEARRAY: {
+ Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0);
+ checkArrayTypeToUnparcel(clazz, (itemType != null) ? itemType : Parcelable.class);
+ object = readParcelableArrayInternal(loader, itemType);
break;
-
- case VAL_SPARSEARRAY:
- object = readSparseArray(loader);
+ }
+ case VAL_SPARSEARRAY: {
+ checkTypeToUnparcel(clazz, SparseArray.class);
+ Class<?> itemType = ArrayUtils.getOrNull(itemTypes, 0);
+ object = readSparseArrayInternal(loader, itemType);
break;
-
+ }
case VAL_SPARSEBOOLEANARRAY:
object = readSparseBooleanArray();
break;
@@ -4153,7 +4652,7 @@
+ " at offset " + off);
}
if (object != null && clazz != null && !clazz.isInstance(object)) {
- throw new BadParcelableException("Unparcelled object " + object
+ throw new BadTypeParcelableException("Unparcelled object " + object
+ " is not an instance of required class " + clazz.getName()
+ " provided in the parameter");
}
@@ -4180,6 +4679,38 @@
}
/**
+ * Checks that an array of type T[], where T is {@code componentTypeToUnparcel}, is a subtype of
+ * {@code requiredArrayType}.
+ */
+ private void checkArrayTypeToUnparcel(@Nullable Class<?> requiredArrayType,
+ Class<?> componentTypeToUnparcel) {
+ if (requiredArrayType != null) {
+ // In Java 12, we could use componentTypeToUnparcel.arrayType() for the check
+ Class<?> requiredComponentType = requiredArrayType.getComponentType();
+ if (requiredComponentType == null) {
+ throw new BadTypeParcelableException(
+ "About to unparcel an array but type "
+ + requiredArrayType.getCanonicalName()
+ + " required by caller is not an array.");
+ }
+ checkTypeToUnparcel(requiredComponentType, componentTypeToUnparcel);
+ }
+ }
+
+ /**
+ * Checks that {@code typeToUnparcel} is a subtype of {@code requiredType}, if {@code
+ * requiredType} is not {@code null}.
+ */
+ private void checkTypeToUnparcel(@Nullable Class<?> requiredType, Class<?> typeToUnparcel) {
+ if (requiredType != null && !requiredType.isAssignableFrom(typeToUnparcel)) {
+ throw new BadTypeParcelableException(
+ "About to unparcel a " + typeToUnparcel.getCanonicalName()
+ + ", which is not a subtype of type " + requiredType.getCanonicalName()
+ + " required by caller.");
+ }
+ }
+
+ /**
* Read and return a new Parcelable from the parcel. The given class loader
* will be used to load any enclosed Parcelables. If it is null, the default
* class loader will be used.
@@ -4309,7 +4840,7 @@
if (clazz != null) {
Class<?> parcelableClass = creator.getClass().getEnclosingClass();
if (!clazz.isAssignableFrom(parcelableClass)) {
- throw new BadParcelableException("Parcelable creator " + name + " is not "
+ throw new BadTypeParcelableException("Parcelable creator " + name + " is not "
+ "a subclass of required class " + clazz.getName()
+ " provided in the parameter");
}
@@ -4332,7 +4863,7 @@
}
if (clazz != null) {
if (!clazz.isAssignableFrom(parcelableClass)) {
- throw new BadParcelableException("Parcelable creator " + name + " is not "
+ throw new BadTypeParcelableException("Parcelable creator " + name + " is not "
+ "a subclass of required class " + clazz.getName()
+ " provided in the parameter");
}
@@ -4393,15 +4924,7 @@
@Deprecated
@Nullable
public Parcelable[] readParcelableArray(@Nullable ClassLoader loader) {
- int N = readInt();
- if (N < 0) {
- return null;
- }
- Parcelable[] p = new Parcelable[N];
- for (int i = 0; i < N; i++) {
- p[i] = readParcelable(loader);
- }
- return p;
+ return readParcelableArrayInternal(loader, /* clazz */ null);
}
/**
@@ -4413,14 +4936,20 @@
* trying to instantiate an element.
*/
@SuppressLint({"ArrayReturn", "NullableCollection"})
- @SuppressWarnings("unchecked")
@Nullable
public <T> T[] readParcelableArray(@Nullable ClassLoader loader, @NonNull Class<T> clazz) {
+ return readParcelableArrayInternal(loader, requireNonNull(clazz));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ private <T> T[] readParcelableArrayInternal(@Nullable ClassLoader loader,
+ @Nullable Class<T> clazz) {
int n = readInt();
if (n < 0) {
return null;
}
- T[] p = (T[]) Array.newInstance(clazz, n);
+ T[] p = (T[]) ((clazz == null) ? new Parcelable[n] : Array.newInstance(clazz, n));
for (int i = 0; i < n; i++) {
p[i] = readParcelableInternal(loader, clazz);
}
@@ -4483,7 +5012,7 @@
// the class the same way as ObjectInputStream, using the provided classloader.
Class<?> cl = Class.forName(name, false, loader);
if (!clazz.isAssignableFrom(cl)) {
- throw new BadParcelableException("Serializable object "
+ throw new BadTypeParcelableException("Serializable object "
+ cl.getName() + " is not a subclass of required class "
+ clazz.getName() + " provided in the parameter");
}
@@ -4508,7 +5037,7 @@
// the deserialized object, as we cannot resolve the class the same way as
// ObjectInputStream.
if (!clazz.isAssignableFrom(object.getClass())) {
- throw new BadParcelableException("Serializable object "
+ throw new BadTypeParcelableException("Serializable object "
+ object.getClass().getName() + " is not a subclass of required class "
+ clazz.getName() + " provided in the parameter");
}
@@ -4581,6 +5110,7 @@
}
private void freeBuffer() {
+ mFlags = 0;
resetSqaushingState();
if (mOwnsNativeParcelObject) {
nativeFreeBuffer(mNativePtr);
@@ -4617,7 +5147,26 @@
readMapInternal(outVal, n, loader, /* clazzKey */null, /* clazzValue */null);
}
- /* package */ <K, V> void readMapInternal(@NonNull Map<? super K, ? super V> outVal, int n,
+ @Nullable
+ private <K, V> HashMap<K, V> readHashMapInternal(@Nullable ClassLoader loader,
+ @NonNull Class<? extends K> clazzKey, @NonNull Class<? extends V> clazzValue) {
+ int n = readInt();
+ if (n < 0) {
+ return null;
+ }
+ HashMap<K, V> map = new HashMap<>(n);
+ readMapInternal(map, n, loader, clazzKey, clazzValue);
+ return map;
+ }
+
+ private <K, V> void readMapInternal(@NonNull Map<? super K, ? super V> outVal,
+ @Nullable ClassLoader loader, @Nullable Class<K> clazzKey,
+ @Nullable Class<V> clazzValue) {
+ int n = readInt();
+ readMapInternal(outVal, n, loader, clazzKey, clazzValue);
+ }
+
+ private <K, V> void readMapInternal(@NonNull Map<? super K, ? super V> outVal, int n,
@Nullable ClassLoader loader, @Nullable Class<K> clazzKey,
@Nullable Class<V> clazzValue) {
while (n > 0) {
@@ -4628,7 +5177,7 @@
}
}
- /* package */ void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal,
+ private void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal,
int size, @Nullable ClassLoader loader) {
readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader);
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 944b717..a3b836a 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -674,10 +674,12 @@
}
try {
if (!rs.allocateSpaceForUpdate(packageFile)) {
+ rs.clearBcb();
throw new IOException("Failed to allocate space for update "
+ packageFile.getAbsolutePath());
}
} catch (RemoteException e) {
+ rs.clearBcb();
e.rethrowAsRuntimeException();
}
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index a5a40ad..4e69952 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -26,6 +26,7 @@
* @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 @@
* @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 @@
*
* @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 @@
*
* @return GsiProgress
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
GsiProgress getInstallationProgress();
/**
@@ -66,21 +71,25 @@
*
* @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 @@
*
* @return true if the call succeeds
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean remove();
/**
@@ -97,6 +107,7 @@
*
* @return true if the call succeeds
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean setEnable(boolean enable, boolean oneShot);
/**
@@ -106,6 +117,7 @@
* @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 @@
* @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 @@
* @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/provider/Settings.java b/core/java/android/provider/Settings.java
index d0ef546..e79cc32 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -238,6 +238,20 @@
"android.settings.TETHER_PROVISIONING_UI";
/**
+ * Activity Action: Show a dialog activity to notify tethering is NOT supported by carrier.
+ *
+ * When {@link android.telephony.CarrierConfigManager#KEY_CARRIER_SUPPORTS_TETHERING_BOOL}
+ * is false, and tethering is started by Settings, this dialog activity will be started to
+ * tell the user that tethering is not supported by carrier.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @SystemApi
+ public static final String ACTION_TETHER_UNSUPPORTED_CARRIER_UI =
+ "android.settings.TETHER_UNSUPPORTED_CARRIER_UI";
+
+ /**
* Activity Action: Show settings to allow entering/exiting airplane mode.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 1b26465..b79b3d8 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -3584,6 +3584,23 @@
"content://telephony/carriers/enforce_managed");
/**
+ * The {@code content://} style URL for the perferred APN used for internet.
+ *
+ * @hide
+ */
+ public static final Uri PREFERRED_APN_URI = Uri.parse(
+ "content://telephony/carriers/preferapn/subId/");
+
+ /**
+ * The {@code content://} style URL for the perferred APN set id.
+ *
+ * @hide
+ */
+ public static final Uri PREFERRED_APN_SET_URI = Uri.parse(
+ "content://telephony/carriers/preferapnset/subId/");
+
+
+ /**
* The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
* @hide
*/
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 3b4f7e2..f900558 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -317,16 +317,35 @@
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/autofill/OWNERS b/core/java/android/service/autofill/OWNERS
index a088632..9a30e82 100644
--- a/core/java/android/service/autofill/OWNERS
+++ b/core/java/android/service/autofill/OWNERS
@@ -1,9 +1,3 @@
# Bug component: 351486
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/java/android/service/contentcapture/OWNERS b/core/java/android/service/contentcapture/OWNERS
index 6337327..24561c5 100644
--- a/core/java/android/service/contentcapture/OWNERS
+++ b/core/java/android/service/contentcapture/OWNERS
@@ -1,9 +1,3 @@
# Bug component: 544200
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/contentcapture/OWNERS
diff --git a/core/java/android/service/contentsuggestions/OWNERS b/core/java/android/service/contentsuggestions/OWNERS
index 46b5ea0..72fe0b1 100644
--- a/core/java/android/service/contentsuggestions/OWNERS
+++ b/core/java/android/service/contentsuggestions/OWNERS
@@ -1,7 +1,2 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+
+include /core/java/android/app/contentsuggestions/OWNERS
diff --git a/core/java/android/service/resumeonreboot/OWNERS b/core/java/android/service/resumeonreboot/OWNERS
index 3a127d5..721fbaf 100644
--- a/core/java/android/service/resumeonreboot/OWNERS
+++ b/core/java/android/service/resumeonreboot/OWNERS
@@ -1,2 +1 @@
-xunchang@google.com
-zhaojiac@google.com
+ejyzhang@google.com
\ No newline at end of file
diff --git a/core/java/android/service/textclassifier/OWNERS b/core/java/android/service/textclassifier/OWNERS
index a535f52..c85c69e 100644
--- a/core/java/android/service/textclassifier/OWNERS
+++ b/core/java/android/service/textclassifier/OWNERS
@@ -1,9 +1,3 @@
# Bug component: 709498
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+include /core/java/android/view/textclassifier/OWNERS
diff --git a/core/java/android/service/tracing/TraceReportService.java b/core/java/android/service/tracing/TraceReportService.java
index 3d16a3d..6fdc8e8 100644
--- a/core/java/android/service/tracing/TraceReportService.java
+++ b/core/java/android/service/tracing/TraceReportService.java
@@ -112,7 +112,6 @@
}
}
- // Methods to override.
/**
* Called when a trace is reported and sent to this class.
*
@@ -123,15 +122,10 @@
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) {
+ private 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.");
@@ -153,10 +147,12 @@
/**
* Returns an IBinder for handling binder calls from system_server.
+ *
+ * @hide
*/
@Nullable
@Override
- public IBinder onBind(@NonNull Intent intent) {
+ public final IBinder onBind(@NonNull Intent intent) {
if (mMessenger == null) {
mMessenger = new Messenger(new Handler(Looper.getMainLooper(), this::onMessage));
}
diff --git a/core/java/android/service/translation/OWNERS b/core/java/android/service/translation/OWNERS
index a1e663a..440f9a8 100644
--- a/core/java/android/service/translation/OWNERS
+++ b/core/java/android/service/translation/OWNERS
@@ -1,8 +1,3 @@
# Bug component: 994311
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+include /core/java/android/view/translation/OWNERS
diff --git a/core/java/android/service/voice/OWNERS b/core/java/android/service/voice/OWNERS
index 46b5ea0..59a0c2e 100644
--- a/core/java/android/service/voice/OWNERS
+++ b/core/java/android/service/voice/OWNERS
@@ -1,7 +1,3 @@
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
-augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+# Bug component: 533220
+
+include /core/java/android/app/assist/OWNERS
diff --git a/core/java/android/tracing/OWNERS b/core/java/android/tracing/OWNERS
index f5de4eb..7d1b48b 100644
--- a/core/java/android/tracing/OWNERS
+++ b/core/java/android/tracing/OWNERS
@@ -1,2 +1,2 @@
-cfijalkovich@google.com
carmenjackson@google.com
+include platform/external/perfetto:/OWNERS
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 4ac3178..40beab3 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -81,7 +81,16 @@
/** Calculates and returns the age of this result. */
public long getAgeMillis() {
- return SystemClock.elapsedRealtime() - mElapsedRealtimeMillis;
+ return getAgeMillis(SystemClock.elapsedRealtime());
+ }
+
+ /**
+ * Calculates and returns the age of this result relative to currentElapsedRealtimeMillis.
+ *
+ * @param currentElapsedRealtimeMillis - reference elapsed real time
+ */
+ public long getAgeMillis(long currentElapsedRealtimeMillis) {
+ return currentElapsedRealtimeMillis - mElapsedRealtimeMillis;
}
@Override
@@ -256,6 +265,13 @@
return mTimeResult;
}
+ /** Clears the last received NTP. Intended for use during tests. */
+ public void clearCachedTimeResult() {
+ synchronized (this) {
+ mTimeResult = null;
+ }
+ }
+
private static class NtpConnectionInfo {
@NonNull private final String mServer;
diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS
index 5425c21..d4cf6e6 100644
--- a/core/java/android/util/OWNERS
+++ b/core/java/android/util/OWNERS
@@ -1,8 +1,12 @@
+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
per-file PackageUtils.java = file:/core/java/android/content/pm/OWNERS
+
+per-file NtpTrustedTime.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
+per-file TimeUtils.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
+per-file TrustedTime.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index c7d9b9c..c8c1fd4 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -407,20 +407,6 @@
}
}
- 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 b07b522..15215c6 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -444,20 +444,6 @@
}
}
- 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 73f7543..f6b85fd 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -551,27 +551,6 @@
}
/**
- * 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 c7c465d..adf53c2 100644
--- a/core/java/android/util/apk/VerityBuilder.java
+++ b/core/java/android/util/apk/VerityBuilder.java
@@ -143,25 +143,6 @@
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/view/OWNERS b/core/java/android/view/OWNERS
index c74e428..b166fa6 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -11,6 +11,9 @@
roosa@google.com
jreck@google.com
+# Autofill
+per-file ViewStructure.java = file:/core/java/android/service/autofill/OWNERS
+
# Display
per-file Display*.java = file:/services/core/java/com/android/server/display/OWNERS
per-file Display*.aidl = file:/services/core/java/com/android/server/display/OWNERS
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 00f4eb8..5b0bc4a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3128,7 +3128,8 @@
/**
* The window is allowed to extend into the {@link DisplayCutout} area, only if the
- * {@link DisplayCutout} is fully contained within a system bar. Otherwise, the window is
+ * {@link DisplayCutout} is fully contained within a system bar or the {@link DisplayCutout}
+ * is not deeper than 16 dp, but this depends on the OEM choice. Otherwise, the window is
* laid out such that it does not overlap with the {@link DisplayCutout} area.
*
* <p>
@@ -3143,6 +3144,13 @@
* The usual precautions for not overlapping with the status and navigation bar are
* sufficient for ensuring that no important content overlaps with the DisplayCutout.
*
+ * <p>
+ * Note: OEMs can have an option to allow the window to always extend into the
+ * {@link DisplayCutout} area, no matter the cutout flag set, when the {@link DisplayCutout}
+ * is on the different side from system bars, only if the {@link DisplayCutout} overlaps at
+ * most 16dp with the windows.
+ * In such case, OEMs must provide an opt-in/out affordance for users.
+ *
* @see DisplayCutout
* @see WindowInsets
* @see #layoutInDisplayCutoutMode
@@ -3155,8 +3163,16 @@
* The window is always allowed to extend into the {@link DisplayCutout} areas on the short
* edges of the screen.
*
+ * <p>
* The window will never extend into a {@link DisplayCutout} area on the long edges of the
- * screen.
+ * screen, unless the {@link DisplayCutout} is not deeper than 16 dp, but this depends on
+ * the OEM choice.
+ *
+ * <p>
+ * Note: OEMs can have an option to allow the window to extend into the
+ * {@link DisplayCutout} area on the long edge side, only if the cutout overlaps at most
+ * 16dp with the windows. In such case, OEMs must provide an opt-in/out affordance for
+ * users.
*
* <p>
* The window must make sure that no important content overlaps with the
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
index a088632..108c42c 100644
--- a/core/java/android/view/autofill/OWNERS
+++ b/core/java/android/view/autofill/OWNERS
@@ -1,9 +1,7 @@
# Bug component: 351486
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index 6337327..1a5cb1e4 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -1,9 +1,7 @@
# Bug component: 544200
-joannechung@google.com
-adamhe@google.com
-tymtsai@google.com
-lpeter@google.com
augale@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+joannechung@google.com
+markpun@google.com
+lpeter@google.com
+tymtsai@google.com
diff --git a/core/java/android/view/inputmethod/OWNERS b/core/java/android/view/inputmethod/OWNERS
index d7db7c7..9fa7e8f 100644
--- a/core/java/android/view/inputmethod/OWNERS
+++ b/core/java/android/view/inputmethod/OWNERS
@@ -3,4 +3,4 @@
include /services/core/java/com/android/server/inputmethod/OWNERS
-per-file *InlineSuggestion* = file:/core/java/android/service/autofill/OWNERS
+per-file *InlineSuggestion* = file:/core/java/android/view/autofill/OWNERS
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index 4bcdeea..a205be2 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -2,8 +2,6 @@
mns@google.com
toki@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
augale@google.com
joannechung@google.com
tonymak@google.com
diff --git a/core/java/android/view/textclassifier/logging/OWNERS b/core/java/android/view/textclassifier/logging/OWNERS
deleted file mode 100644
index ac80d9f..0000000
--- a/core/java/android/view/textclassifier/logging/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# Bug component: 709498
-
-mns@google.com
-toki@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
-augale@google.com
-joannechung@google.com
diff --git a/core/java/android/view/translation/OWNERS b/core/java/android/view/translation/OWNERS
index a1e663a..b772ad3 100644
--- a/core/java/android/view/translation/OWNERS
+++ b/core/java/android/view/translation/OWNERS
@@ -1,8 +1,7 @@
# Bug component: 994311
-adamhe@google.com
augale@google.com
joannechung@google.com
+markpun@google.com
lpeter@google.com
-svetoslavganov@google.com
tymtsai@google.com
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 2d1f17a..a0ec48b 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -297,12 +297,12 @@
} else {
mTextClassification = null;
}
- final SelectionModifierCursorController controller = mEditor.getSelectionController();
- if (controller != null
- && (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
- controller.show();
- }
if (mEditor.startActionModeInternal(actionMode)) {
+ final SelectionModifierCursorController controller = mEditor.getSelectionController();
+ if (controller != null
+ && (mTextView.isTextSelectable() || mTextView.isTextEditable())) {
+ controller.show();
+ }
if (result != null) {
switch (actionMode) {
case Editor.TextActionMode.SELECTION:
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f5c1bcf..9791da5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4347,7 +4347,7 @@
* 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 @@
* 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.
@@ -12521,7 +12521,9 @@
/**
* Called when a context menu option for the text view is selected. Currently
* this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut},
- * {@link android.R.id#copy}, {@link android.R.id#paste} or {@link android.R.id#shareText}.
+ * {@link android.R.id#copy}, {@link android.R.id#paste},
+ * {@link android.R.id#pasteAsPlainText} (starting at API level 23) or
+ * {@link android.R.id#shareText}.
*
* @return true if the context menu item action was performed.
*/
@@ -12712,6 +12714,7 @@
* method. The default actions can also be removed from the menu using
* {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
* {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste},
+ * {@link android.R.id#pasteAsPlainText} (starting at API level 23),
* {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters.
*
* <p>Returning false from
@@ -12750,7 +12753,8 @@
* {@link android.view.ActionMode.Callback#onPrepareActionMode(android.view.ActionMode,
* android.view.Menu)} method. The default actions can also be removed from the menu using
* {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
- * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.</p>
+ * {@link android.R.id#paste}, {@link android.R.id#pasteAsPlainText} (starting at API
+ * level 23) or {@link android.R.id#replaceText} ids as parameters.</p>
*
* <p>Returning false from
* {@link android.view.ActionMode.Callback#onCreateActionMode(android.view.ActionMode,
diff --git a/core/java/android/widget/inline/OWNERS b/core/java/android/widget/inline/OWNERS
new file mode 100644
index 0000000..9a30e82
--- /dev/null
+++ b/core/java/android/widget/inline/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 351486
+
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 2ae56f8..f174498 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -105,6 +105,7 @@
public boolean allowIPv4;
public boolean allowIPv6;
public boolean isMetered = true;
+ public boolean requiresInternetValidation = false;
public Network[] underlyingNetworks;
public ProxyInfo proxyInfo;
@@ -131,6 +132,7 @@
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 @@
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 @@
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 @@
.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 d8dc143..bd3e898 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 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 @@
areAuthParamsInline = in.readBoolean();
isRestrictedToTestNetworks = in.readBoolean();
excludeLocalRoutes = in.readBoolean();
+ requiresInternetValidation = in.readBoolean();
}
/**
@@ -239,6 +243,7 @@
out.writeBoolean(areAuthParamsInline);
out.writeBoolean(isRestrictedToTestNetworks);
out.writeBoolean(excludeLocalRoutes);
+ out.writeBoolean(requiresInternetValidation);
}
/**
@@ -258,9 +263,11 @@
// 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 @@
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 @@
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 @@
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 @@
&& 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/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 58a0622..a234743 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12003,59 +12003,57 @@
long totalRxPackets = 0;
long totalTxPackets = 0;
if (delta != null) {
- NetworkStats.Entry entry = new NetworkStats.Entry();
- final int size = delta.size();
- for (int i = 0; i < size; i++) {
- entry = delta.getValues(i, entry);
- if (entry.rxPackets == 0 && entry.txPackets == 0) {
+ for (NetworkStats.Entry entry : delta) {
+ if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
continue;
}
if (DEBUG_ENERGY) {
- Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
- + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
- + " txPackets=" + entry.txPackets);
+ Slog.d(TAG, "Mobile uid " + entry.getUid() + ": delta rx="
+ + entry.getRxBytes() + " tx=" + entry.getTxBytes()
+ + " rxPackets=" + entry.getRxPackets()
+ + " txPackets=" + entry.getTxPackets());
}
- totalRxPackets += entry.rxPackets;
- totalTxPackets += entry.txPackets;
+ totalRxPackets += entry.getRxPackets();
+ totalTxPackets += entry.getTxPackets();
- final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
- u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
- entry.rxPackets);
- u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
- entry.txPackets);
- if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+ final Uid u = getUidStatsLocked(
+ mapUid(entry.getUid()), elapsedRealtimeMs, uptimeMs);
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.getRxBytes(),
+ entry.getRxPackets());
+ u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.getTxBytes(),
+ entry.getTxPackets());
+ if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
- entry.rxBytes, entry.rxPackets);
+ entry.getRxBytes(), entry.getRxPackets());
u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
- entry.txBytes, entry.txPackets);
+ entry.getTxBytes(), entry.getTxPackets());
}
mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
- entry.rxBytes);
+ entry.getRxBytes());
mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
- entry.txBytes);
+ entry.getTxBytes());
mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
- entry.rxPackets);
+ entry.getRxPackets());
mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
- entry.txPackets);
+ entry.getTxPackets());
}
// Now distribute proportional blame to the apps that did networking.
long totalPackets = totalRxPackets + totalTxPackets;
if (totalPackets > 0) {
- for (int i = 0; i < size; i++) {
- entry = delta.getValues(i, entry);
- if (entry.rxPackets == 0 && entry.txPackets == 0) {
+ for (NetworkStats.Entry entry : delta) {
+ if (entry.getRxPackets() == 0 && entry.getTxPackets() == 0) {
continue;
}
- final Uid u = getUidStatsLocked(mapUid(entry.uid),
+ final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
elapsedRealtimeMs, uptimeMs);
// Distribute total radio active time in to this app.
- final long appPackets = entry.rxPackets + entry.txPackets;
+ final long appPackets = entry.getRxPackets() + entry.getTxPackets();
final long appRadioTimeUs =
(totalAppRadioTimeUs * appPackets) / totalPackets;
u.noteMobileRadioActiveTimeLocked(appRadioTimeUs);
@@ -12076,16 +12074,16 @@
if (deltaInfo != null) {
ControllerActivityCounterImpl activityCounter =
u.getOrCreateModemControllerActivityLocked();
- if (totalRxPackets > 0 && entry.rxPackets > 0) {
- final long rxMs = (entry.rxPackets
+ if (totalRxPackets > 0 && entry.getRxPackets() > 0) {
+ final long rxMs = (entry.getRxPackets()
* deltaInfo.getReceiveTimeMillis()) / totalRxPackets;
activityCounter.getRxTimeCounter().addCountLocked(rxMs);
}
- if (totalTxPackets > 0 && entry.txPackets > 0) {
+ if (totalTxPackets > 0 && entry.getTxPackets() > 0) {
for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels();
lvl++) {
- long txMs = entry.txPackets
+ long txMs = entry.getTxPackets()
* deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl);
txMs /= totalTxPackets;
activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
diff --git a/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java b/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java
index 615e4b79..a03bac4 100644
--- a/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/SystemServerClassLoaderFactory.java
@@ -29,22 +29,66 @@
private static final ArrayMap<String, PathClassLoader> sLoadedPaths = new ArrayMap<>();
/**
- * Creates and caches a ClassLoader for the jar at the given path, or returns a cached
- * ClassLoader if it exists.
+ * Creates and caches a ClassLoader for the jar at the given path.
+ *
+ * This method should only be called by ZygoteInit to prefetch jars. For other users, use
+ * {@link getOrCreateClassLoader} instead.
*
* The parent class loader should always be the system server class loader. Changing it has
* implications that require discussion with the mainline team.
*
* @hide for internal use only
*/
- public static PathClassLoader getOrCreateClassLoader(String path, ClassLoader parent) {
- PathClassLoader pathClassLoader = sLoadedPaths.get(path);
- if (pathClassLoader == null) {
- pathClassLoader = (PathClassLoader) ClassLoaderFactory.createClassLoader(
- path, /*librarySearchPath=*/null, /*libraryPermittedPath=*/null, parent,
- Build.VERSION.SDK_INT, /*isNamespaceShared=*/true , /*classLoaderName=*/null);
- sLoadedPaths.put(path, pathClassLoader);
+ /* package */ static PathClassLoader createClassLoader(String path, ClassLoader parent) {
+ if (sLoadedPaths.containsKey(path)) {
+ throw new IllegalStateException("A ClassLoader for " + path + " already exists");
}
+ PathClassLoader pathClassLoader = (PathClassLoader) ClassLoaderFactory.createClassLoader(
+ path, /*librarySearchPath=*/null, /*libraryPermittedPath=*/null, parent,
+ Build.VERSION.SDK_INT, /*isNamespaceShared=*/true , /*classLoaderName=*/null);
+ sLoadedPaths.put(path, pathClassLoader);
return pathClassLoader;
}
+
+ /**
+ * Returns a cached ClassLoader to be used at runtime for the jar at the given path. Or, creates
+ * one if it is not prefetched and is allowed to be created at runtime.
+ *
+ * The parent class loader should always be the system server class loader. Changing it has
+ * implications that require discussion with the mainline team.
+ *
+ * @hide for internal use only
+ */
+ public static PathClassLoader getOrCreateClassLoader(
+ String path, ClassLoader parent, boolean isTestOnly) {
+ PathClassLoader pathClassLoader = sLoadedPaths.get(path);
+ if (pathClassLoader != null) {
+ return pathClassLoader;
+ }
+ if (!allowClassLoaderCreation(path, isTestOnly)) {
+ throw new RuntimeException("Creating a ClassLoader from " + path + " is not allowed. "
+ + "Please make sure that the jar is listed in "
+ + "`PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS` in the Makefile and added as a "
+ + "`standalone_contents` of a `systemserverclasspath_fragment` in "
+ + "`Android.bp`.");
+ }
+ return createClassLoader(path, parent);
+ }
+
+ /**
+ * Returns whether a class loader for the jar is allowed to be created at runtime.
+ */
+ private static boolean allowClassLoaderCreation(String path, boolean isTestOnly) {
+ // Currently, we only enforce prefetching for APEX jars.
+ if (!path.startsWith("/apex/")) {
+ return true;
+ }
+ // APEXes for testing only are okay to ignore.
+ if (isTestOnly) {
+ return true;
+ }
+ return false;
+ }
+
+
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 611f644..e5e6949 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -586,7 +586,7 @@
}
for (String jar : envStr.split(":")) {
try {
- SystemServerClassLoaderFactory.getOrCreateClassLoader(
+ SystemServerClassLoaderFactory.createClassLoader(
jar, getOrCreateSystemServerClassLoader());
} catch (Error e) {
// We don't want the process to crash for this error because prefetching is just an
@@ -713,7 +713,7 @@
"--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 8770267..76f7b21 100644
--- a/core/java/com/android/internal/security/VerityUtils.java
+++ b/core/java/com/android/internal/security/VerityUtils.java
@@ -18,28 +18,15 @@
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 @@
/** 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 @@
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/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index c6fd6ee..55df09a 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -888,6 +888,15 @@
}
}
+ /**
+ * Returns the {@code i}-th item in {@code items}, if it exists and {@code items} is not {@code
+ * null}, otherwise returns {@code null}.
+ */
+ @Nullable
+ public static <T> T getOrNull(@Nullable T[] items, int i) {
+ return (items != null && items.length > i) ? items[i] : null;
+ }
+
public static @Nullable <T> T firstOrNull(T[] items) {
return items.length > 0 ? items[0] : null;
}
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 2b7f8b2..354dd9a 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -4,3 +4,4 @@
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 0000000..ce9302a
--- /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/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index ae9d716..fb0b7fd 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -112,17 +112,74 @@
public final String name;
public final String filename;
public final String[] dependencies;
+
+ /**
+ * SDK version this library was added to the BOOTCLASSPATH.
+ *
+ * <p>At the SDK level specified in this field and higher, the apps' uses-library tags for
+ * this library will be ignored, since the library is always available on BOOTCLASSPATH.
+ *
+ * <p>0 means not specified.
+ */
+ public final int onBootclasspathSince;
+
+ /**
+ * SDK version this library was removed from the BOOTCLASSPATH.
+ *
+ * <p>At the SDK level specified in this field and higher, this library needs to be
+ * explicitly added by apps. For compatibility reasons, when an app
+ * targets an SDK less than the value of this attribute, this library is automatically
+ * added.
+ *
+ * <p>0 means not specified.
+ */
+ public final int onBootclasspathBefore;
+
+ /**
+ * Declares whether this library can be safely ignored from <uses-library> tags.
+ *
+ * <p> This can happen if the library initially had to be explicitly depended-on using that
+ * tag but has since been moved to the BOOTCLASSPATH which means now is always available
+ * and the tag is no longer required.
+ */
+ public final boolean canBeSafelyIgnored;
+
public final boolean isNative;
- SharedLibraryEntry(String name, String filename, String[] dependencies) {
- this(name, filename, dependencies, false /* isNative */);
+
+ @VisibleForTesting
+ public SharedLibraryEntry(String name, String filename, String[] dependencies,
+ boolean isNative) {
+ this(name, filename, dependencies, 0 /* onBootclasspathSince */,
+ 0 /* onBootclasspathBefore */, isNative);
}
- SharedLibraryEntry(String name, String filename, String[] dependencies, boolean isNative) {
+ @VisibleForTesting
+ public SharedLibraryEntry(String name, String filename, String[] dependencies,
+ int onBootclasspathSince, int onBootclassPathBefore) {
+ this(name, filename, dependencies, onBootclasspathSince, onBootclassPathBefore,
+ false /* isNative */);
+ }
+
+ SharedLibraryEntry(String name, String filename, String[] dependencies,
+ int onBootclasspathSince, int onBootclasspathBefore, boolean isNative) {
this.name = name;
this.filename = filename;
this.dependencies = dependencies;
+ this.onBootclasspathSince = onBootclasspathSince;
+ this.onBootclasspathBefore = onBootclasspathBefore;
this.isNative = isNative;
+
+ canBeSafelyIgnored = this.onBootclasspathSince != 0
+ && isSdkAtLeast(this.onBootclasspathSince);
+ }
+
+ private static boolean isSdkAtLeast(int level) {
+ if ("REL".equals(Build.VERSION.CODENAME)) {
+ return Build.VERSION.SDK_INT >= level;
+ }
+ return level == Build.VERSION_CODES.CUR_DEVELOPMENT
+ || Build.VERSION.SDK_INT >= level;
}
}
@@ -509,12 +566,14 @@
}
private void readAllPermissions() {
+ final XmlPullParser parser = Xml.newPullParser();
+
// Read configuration from system
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
// Vendors are only allowed to customize these
@@ -524,18 +583,18 @@
// For backward compatibility
vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
}
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
String vendorSkuProperty = SystemProperties.get(VENDOR_SKU_PROPERTY, "");
if (!vendorSkuProperty.isEmpty()) {
String vendorSkuDir = "sku_" + vendorSkuProperty;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "sysconfig", vendorSkuDir),
vendorPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getVendorDirectory(), "etc", "permissions", vendorSkuDir),
vendorPermissionFlag);
}
@@ -543,18 +602,18 @@
// Allow ODM to customize system configs as much as Vendor, because /odm is another
// vendor partition other than /vendor.
int odmPermissionFlag = vendorPermissionFlag;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
if (!skuProperty.isEmpty()) {
String skuDir = "sku_" + skuProperty;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions", skuDir),
odmPermissionFlag);
}
@@ -562,9 +621,9 @@
// Allow OEM to customize these
int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS
| ALLOW_VENDOR_APEX;
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
// Allow Product to customize these configs
@@ -579,15 +638,15 @@
// DEVICE_INITIAL_SDK_INT for the devices without product interface enforcement.
productPermissionFlag = ALLOW_ALL;
}
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
// Allow /system_ext to customize all system configs
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
- readPermissions(Environment.buildPath(
+ readPermissions(parser, Environment.buildPath(
Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
// Skip loading configuration from apex if it is not a system process.
@@ -601,12 +660,14 @@
if (f.isFile() || f.getPath().contains("@")) {
continue;
}
- readPermissions(Environment.buildPath(f, "etc", "permissions"), apexPermissionFlag);
+ readPermissions(parser, Environment.buildPath(f, "etc", "permissions"),
+ apexPermissionFlag);
}
+ pruneVendorApexPrivappAllowlists();
}
@VisibleForTesting
- public void readPermissions(File libraryDir, int permissionFlag) {
+ public void readPermissions(final XmlPullParser parser, File libraryDir, int permissionFlag) {
// Read permissions from given directory.
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
if (permissionFlag == ALLOW_ALL) {
@@ -641,12 +702,12 @@
continue;
}
- readPermissionsFromXml(f, permissionFlag);
+ readPermissionsFromXml(parser, f, permissionFlag);
}
// Read platform permissions last so it will take precedence
if (platformFile != null) {
- readPermissionsFromXml(platformFile, permissionFlag);
+ readPermissionsFromXml(parser, platformFile, permissionFlag);
}
}
@@ -655,8 +716,9 @@
+ permFile + " at " + parser.getPositionDescription());
}
- private void readPermissionsFromXml(File permFile, int permissionFlag) {
- FileReader permReader = null;
+ private void readPermissionsFromXml(final XmlPullParser parser, File permFile,
+ int permissionFlag) {
+ final FileReader permReader;
try {
permReader = new FileReader(permFile);
} catch (FileNotFoundException e) {
@@ -668,7 +730,6 @@
final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
try {
- XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);
int type;
@@ -789,11 +850,17 @@
XmlUtils.skipCurrentTag(parser);
}
} break;
+ case "apex-library":
+ // "apex-library" is meant to behave exactly like "library"
case "library": {
if (allowLibs) {
String lname = parser.getAttributeValue(null, "name");
String lfile = parser.getAttributeValue(null, "file");
String ldependency = parser.getAttributeValue(null, "dependency");
+ int minDeviceSdk = XmlUtils.readIntAttribute(parser, "min-device-sdk",
+ 0);
+ int maxDeviceSdk = XmlUtils.readIntAttribute(parser, "max-device-sdk",
+ 0);
if (lname == null) {
Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
+ parser.getPositionDescription());
@@ -801,10 +868,34 @@
Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
+ parser.getPositionDescription());
} else {
- //Log.i(TAG, "Got library " + lname + " in " + lfile);
- SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
- ldependency == null ? new String[0] : ldependency.split(":"));
- mSharedLibraries.put(lname, entry);
+ boolean allowedMinSdk = minDeviceSdk <= Build.VERSION.SDK_INT;
+ boolean allowedMaxSdk =
+ maxDeviceSdk == 0 || maxDeviceSdk >= Build.VERSION.SDK_INT;
+ final boolean exists = new File(lfile).exists();
+ if (allowedMinSdk && allowedMaxSdk && exists) {
+ int bcpSince = XmlUtils.readIntAttribute(parser,
+ "on-bootclasspath-since", 0);
+ int bcpBefore = XmlUtils.readIntAttribute(parser,
+ "on-bootclasspath-before", 0);
+ SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
+ ldependency == null
+ ? new String[0] : ldependency.split(":"),
+ bcpSince, bcpBefore);
+ mSharedLibraries.put(lname, entry);
+ } else {
+ final StringBuilder msg = new StringBuilder(
+ "Ignore shared library ").append(lname).append(":");
+ if (!allowedMinSdk) {
+ msg.append(" min-device-sdk=").append(minDeviceSdk);
+ }
+ if (!allowedMaxSdk) {
+ msg.append(" max-device-sdk=").append(maxDeviceSdk);
+ }
+ if (!exists) {
+ msg.append(" ").append(lfile).append(" does not exist");
+ }
+ Slog.i(TAG, msg.toString());
+ }
}
} else {
logNotAllowedInPartition(name, permFile, parser);
@@ -1085,7 +1176,8 @@
readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
mSystemExtPrivAppDenyPermissions);
} else if (apex) {
- readApexPrivAppPermissions(parser, permFile);
+ readApexPrivAppPermissions(parser, permFile,
+ Environment.getApexDirectory().toPath());
} else {
readPrivAppPermissions(parser, mPrivAppPermissions,
mPrivAppDenyPermissions);
@@ -1435,6 +1527,21 @@
}
}
+ /**
+ * Prunes out any privileged permission allowlists bundled in vendor apexes.
+ */
+ @VisibleForTesting
+ public void pruneVendorApexPrivappAllowlists() {
+ for (String moduleName: mAllowedVendorApexes.keySet()) {
+ if (mApexPrivAppPermissions.containsKey(moduleName)
+ || mApexPrivAppDenyPermissions.containsKey(moduleName)) {
+ Slog.w(TAG, moduleName + " is a vendor apex, ignore its priv-app allowlist");
+ mApexPrivAppPermissions.remove(moduleName);
+ mApexPrivAppDenyPermissions.remove(moduleName);
+ }
+ }
+ }
+
private void readInstallInUserType(XmlPullParser parser,
Map<String, Set<String>> doInstallMap,
Map<String, Set<String>> nonInstallMap)
@@ -1645,8 +1752,7 @@
/**
* Returns the module name for a file in the apex module's partition.
*/
- private String getApexModuleNameFromFilePath(Path path) {
- final Path apexDirectoryPath = Environment.getApexDirectory().toPath();
+ private String getApexModuleNameFromFilePath(Path path, Path apexDirectoryPath) {
if (!path.startsWith(apexDirectoryPath)) {
throw new IllegalArgumentException("File " + path + " is not part of an APEX.");
}
@@ -1658,9 +1764,14 @@
return path.getName(apexDirectoryPath.getNameCount()).toString();
}
- private void readApexPrivAppPermissions(XmlPullParser parser, File permFile)
- throws IOException, XmlPullParserException {
- final String moduleName = getApexModuleNameFromFilePath(permFile.toPath());
+ /**
+ * Reads the contents of the privileged permission allowlist stored inside an APEX.
+ */
+ @VisibleForTesting
+ public void readApexPrivAppPermissions(XmlPullParser parser, File permFile,
+ Path apexDirectoryPath) throws IOException, XmlPullParserException {
+ final String moduleName =
+ getApexModuleNameFromFilePath(permFile.toPath(), apexDirectoryPath);
final ArrayMap<String, ArraySet<String>> privAppPermissions;
if (mApexPrivAppPermissions.containsKey(moduleName)) {
privAppPermissions = mApexPrivAppPermissions.get(moduleName);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index adcbb425..1d181dd 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -195,7 +195,6 @@
"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",
@@ -244,7 +243,6 @@
"android.hardware.camera.device@3.2",
"libandroid_net",
"libandroidicu",
- "libbpf_android",
"libnetdutils",
"libmemtrack",
"libandroidfw",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 0f98b74..1c4107a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -164,7 +164,6 @@
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 @@
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 a17d807..3a9957b 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -63,6 +63,7 @@
### Graphics ###
per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
per-file android_hardware_HardwareBuffer.cpp = file:/graphics/java/android/graphics/OWNERS
+per-file android_hardware_SyncFence.cpp = file:/graphics/java/android/graphics/OWNERS
### Text ###
per-file android_text_* = file:/core/java/android/text/OWNERS
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 3af55fe..d2d7213 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -81,27 +81,37 @@
void binderDied(const wp<hardware::IBinder>& who)
{
- if (mObject != NULL) {
- JNIEnv* env = javavm_to_jnienv(mVM);
+ JNIEnv* env = javavm_to_jnienv(mVM);
- env->CallStaticVoidMethod(gProxyOffsets.proxy_class, gProxyOffsets.sendDeathNotice, mObject, mCookie);
+ // 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;
+
+ 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 @@
}
}
- bool matches(jobject obj) {
+ bool matchesLocked(jobject obj) {
bool result;
JNIEnv* env = javavm_to_jnienv(mVM);
@@ -129,7 +139,7 @@
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 @@
AutoMutex _l(mLock);
for (const sp<HwBinderDeathRecipient>& deathRecipient : mList) {
- deathRecipient->warnIfStillLive();
+ deathRecipient->warnIfStillLiveLocked();
}
}
@@ -201,7 +211,7 @@
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 9734ab9..0000000
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ /dev/null
@@ -1,73 +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 const JNINativeMethod gQTagUidMethods[] = {
- { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)tagSocketFd},
- { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)untagSocketFd},
-};
-
-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 61b91dd..13ca133 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -873,7 +873,7 @@
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 @@
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 aacf700..5971670 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 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 @@
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);
@@ -1620,7 +1626,7 @@
}
// Also prefetch standalone system server jars. The reason for doing this here is the same
// as above.
- env->CallStaticObjectMethod(gZygoteInitClass, gPrefetchStandaloneSystemServerJars);
+ env->CallStaticVoidMethod(gZygoteInitClass, gPrefetchStandaloneSystemServerJars);
if (env->ExceptionCheck()) {
env->ExceptionClear();
}
diff --git a/core/proto/android/service/diskstats.proto b/core/proto/android/service/diskstats.proto
index f79de39..ad3d673 100644
--- a/core/proto/android/service/diskstats.proto
+++ b/core/proto/android/service/diskstats.proto
@@ -99,6 +99,8 @@
FOLDER_CACHE = 1;
// System folder
FOLDER_SYSTEM = 2;
+ // Metadata folder
+ FOLDER_METADATA = 3;
}
// Which folder?
optional Folder folder = 1;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7f95ca9..111b694 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 -->
<!-- ======================================= -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 590fcf4..ad368a8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1277,6 +1277,8 @@
<java-symbol type="array" name="vendor_required_apps_managed_user" />
<java-symbol type="array" name="vendor_required_apps_managed_profile" />
<java-symbol type="array" name="vendor_required_apps_managed_device" />
+ <java-symbol type="array" name="vendor_required_attestation_certificates" />
+ <java-symbol type="string" name="vendor_required_attestation_revocation_list_url" />
<java-symbol type="array" name="vendor_disallowed_apps_managed_user" />
<java-symbol type="array" name="vendor_disallowed_apps_managed_profile" />
<java-symbol type="array" name="vendor_disallowed_apps_managed_device" />
diff --git a/core/res/res/values/vendor_required_attestation_certificates.xml b/core/res/res/values/vendor_required_attestation_certificates.xml
new file mode 100644
index 0000000..ff7313e
--- /dev/null
+++ b/core/res/res/values/vendor_required_attestation_certificates.xml
@@ -0,0 +1,38 @@
+<?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.
+ */
+-->
+<resources>
+ <!-- The PEM-encoded certificates added here are used for verifying attestations.
+ The trustworthiness of the attestation depends on the root certificate of the chain.
+
+ Certificates that can be used can be retrieved from:
+ https://developer.android.com/training/articles/security-key-attestation#root_certificate.
+
+ If not already present in resource overlay, please add
+ vendor_required_attestation_certificates.xml (matching this file) in vendor overlay
+ with <item></item> of the PEM-encoded root certificates.
+ -->
+ <string-array translatable="false" name="vendor_required_attestation_certificates">
+ </string-array>
+
+ <!-- Url to mapping of revoked certificates' hex encoded serial numbers. Example format
+ can be found at:
+ https://developer.android.com/training/articles/security-key-attestation#certificate_status
+ -->
+ <string translatable="false" name="vendor_required_attestation_revocation_list_url"></string>
+</resources>
diff --git a/core/tests/bandwidthtests/Android.bp b/core/tests/bandwidthtests/Android.bp
index f1ecd45..d0b42f7 100644
--- a/core/tests/bandwidthtests/Android.bp
+++ b/core/tests/bandwidthtests/Android.bp
@@ -23,6 +23,7 @@
android_test {
name: "BandwidthTests",
+ defaults: ["framework-connectivity-test-defaults"],
// Include all test java files.
srcs: ["src/**/*.java"],
libs: [
diff --git a/core/tests/benchmarks/Android.bp b/core/tests/benchmarks/Android.bp
index 4cd5467..0888776 100644
--- a/core/tests/benchmarks/Android.bp
+++ b/core/tests/benchmarks/Android.bp
@@ -27,6 +27,7 @@
java_library {
name: "frameworks-base-core-benchmarks",
+ defaults: ["framework-connectivity-test-defaults"],
installable: true,
srcs: ["src/**/*.java"],
libs: ["caliper-api-target"],
diff --git a/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
index 4b64dfc..cc75579 100644
--- a/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/timedetector/TelephonyTimeSuggestionTest.java
@@ -45,13 +45,13 @@
assertEquals(two, one);
}
- builder1.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+ builder1.setUnixEpochTime(new TimestampedValue<>(1111L, 2222L));
{
TelephonyTimeSuggestion one = builder1.build();
assertEquals(one, one);
}
- builder2.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+ builder2.setUnixEpochTime(new TimestampedValue<>(1111L, 2222L));
{
TelephonyTimeSuggestion one = builder1.build();
TelephonyTimeSuggestion two = builder2.build();
@@ -61,7 +61,7 @@
TelephonyTimeSuggestion.Builder builder3 =
new TelephonyTimeSuggestion.Builder(SLOT_INDEX + 1);
- builder3.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+ builder3.setUnixEpochTime(new TimestampedValue<>(1111L, 2222L));
{
TelephonyTimeSuggestion one = builder1.build();
TelephonyTimeSuggestion three = builder3.build();
@@ -84,7 +84,7 @@
TelephonyTimeSuggestion.Builder builder = new TelephonyTimeSuggestion.Builder(SLOT_INDEX);
assertRoundTripParcelable(builder.build());
- builder.setUtcTime(new TimestampedValue<>(1111L, 2222L));
+ builder.setUnixEpochTime(new TimestampedValue<>(1111L, 2222L));
assertRoundTripParcelable(builder.build());
// DebugInfo should also be stored (but is not checked by equals()
diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS
index 0b94589..a69c6ff 100644
--- a/core/tests/coretests/src/android/content/OWNERS
+++ b/core/tests/coretests/src/android/content/OWNERS
@@ -1,6 +1,7 @@
per-file AssetTest.java = file:/core/java/android/content/res/OWNERS
-per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Context* = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Context* = charlesccchen@google.com
per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
-per-file ComponentCallbacksControllerTest = file:/services/core/java/com/android/server/wm/OWNERS
-per-file ComponentCallbacksControllerTest = charlesccchen@google.com
+per-file *ComponentCallbacks* = file:/services/core/java/com/android/server/wm/OWNERS
+per-file *ComponentCallbacks* = charlesccchen@google.com
diff --git a/core/tests/coretests/src/android/net/NetworkPolicyTest.kt b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
index 3c8f90c..6360a2d 100644
--- a/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
+++ b/core/tests/coretests/src/android/net/NetworkPolicyTest.kt
@@ -16,7 +16,9 @@
package android.net
+import android.net.NetworkStats.METERED_YES
import android.net.NetworkTemplate.MATCH_BLUETOOTH
+import android.net.NetworkTemplate.MATCH_CARRIER
import android.net.NetworkTemplate.MATCH_ETHERNET
import android.net.NetworkTemplate.MATCH_MOBILE
import android.net.NetworkTemplate.MATCH_WIFI
@@ -39,11 +41,19 @@
@Test
fun testTemplateBackupRestore() {
assertPolicyBackupRestore(createTestPolicyForTemplate(
- NetworkTemplate.buildTemplateWifi(TEST_WIFI_NETWORK_KEY1)))
+ NetworkTemplate.Builder(MATCH_WIFI)
+ .setWifiNetworkKeys(setOf(TEST_WIFI_NETWORK_KEY1))
+ .build()))
assertPolicyBackupRestore(createTestPolicyForTemplate(
- NetworkTemplate.buildTemplateMobileAll(TEST_IMSI1)))
+ NetworkTemplate.Builder(MATCH_MOBILE)
+ .setSubscriberIds(setOf(TEST_IMSI1))
+ .setMeteredness(METERED_YES)
+ .build()))
assertPolicyBackupRestore(createTestPolicyForTemplate(
- NetworkTemplate.buildTemplateCarrierMetered(TEST_IMSI1)))
+ NetworkTemplate.Builder(MATCH_CARRIER)
+ .setSubscriberIds(setOf(TEST_IMSI1))
+ .setMeteredness(METERED_YES)
+ .build()))
}
private fun createTestPolicyForTemplate(template: NetworkTemplate): NetworkPolicy {
diff --git a/core/tests/coretests/src/android/widget/OWNERS b/core/tests/coretests/src/android/widget/OWNERS
new file mode 100644
index 0000000..5a9aed3
--- /dev/null
+++ b/core/tests/coretests/src/android/widget/OWNERS
@@ -0,0 +1,5 @@
+include /core/java/android/widget/OWNERS
+
+per-file *SuggestionsPopup* = file:/core/java/android/text/OWNERS
+
+per-file *FloatingToolbar*, *SelectionToolbar* = file:/core/java/android/view/textclassifier/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 40ef04a..152992c 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -17,6 +17,7 @@
package android.widget;
import static android.widget.espresso.CustomViewActions.longPressAtRelativeCoordinates;
+import static android.widget.espresso.DragHandleUtils.assertNoSelectionHandles;
import static android.widget.espresso.DragHandleUtils.onHandleView;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarDoesNotContainItem;
@@ -426,6 +427,41 @@
}
@Test
+ public void testSelectionOnCreateActionModeReturnsFalse() throws Throwable {
+ final String text = "hello world";
+ mActivityRule.runOnUiThread(() -> {
+ final TextView textView = mActivity.findViewById(R.id.textview);
+ textView.setText(text);
+ textView.setCustomSelectionActionModeCallback(
+ new ActionMode.Callback() {
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return false;
+ }
+
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ }
+ });
+ });
+ mInstrumentation.waitForIdleSync();
+ onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf("d")));
+ mInstrumentation.waitForIdleSync();
+ assertNoSelectionHandles();
+ }
+
+ @Test
public void testSelectionRemovedWhenNonselectableTextLosesFocus() throws Throwable {
final TextLinks.TextLink textLink = addLinkifiedTextToTextView(R.id.nonselectable_textview);
final int position = (textLink.getStart() + textLink.getEnd()) / 2;
diff --git a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
index 1cc1894..a48a882 100644
--- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
@@ -16,6 +16,9 @@
package com.android.internal.os;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
@@ -89,7 +92,8 @@
// Note application network activity
NetworkStats networkStats = new NetworkStats(10000, 1)
- .insertEntry("cellular", APP_UID, 0, 0, 1000, 100, 2000, 20, 100);
+ .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
mStatsRule.setNetworkStats(networkStats);
ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
@@ -150,7 +154,8 @@
// Note application network activity
NetworkStats networkStats = new NetworkStats(10000, 1)
- .insertEntry("cellular", APP_UID, 0, 0, 1000, 100, 2000, 20, 100);
+ .addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100));
mStatsRule.setNetworkStats(networkStats);
ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
diff --git a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
index e7ce9a0..0d944e9 100644
--- a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
@@ -16,7 +16,9 @@
package com.android.internal.os;
-
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
@@ -67,8 +69,10 @@
new int[]{NetworkCapabilities.TRANSPORT_WIFI});
NetworkStats networkStats = new NetworkStats(10000, 1)
- .insertEntry("wifi", APP_UID, 0, 0, 1000, 100, 2000, 20, 100)
- .insertEntry("wifi", Process.WIFI_UID, 0, 0, 1111, 111, 2222, 22, 111);
+ .addEntry(new NetworkStats.Entry("wifi", APP_UID, 0, 0, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 1000, 100, 2000, 20, 100))
+ .addEntry(new NetworkStats.Entry("wifi", Process.WIFI_UID, 0, 0, METERED_NO,
+ ROAMING_NO, DEFAULT_NETWORK_NO, 1111, 111, 2222, 22, 111));
mStatsRule.setNetworkStats(networkStats);
return batteryStats;
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 597ea14..12e52c6 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 @@
}
@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/core/tests/utillib/Android.bp b/core/tests/utillib/Android.bp
index d40d1d2..1d5c16c 100644
--- a/core/tests/utillib/Android.bp
+++ b/core/tests/utillib/Android.bp
@@ -23,6 +23,7 @@
java_library {
name: "frameworks-core-util-lib",
+ defaults: ["framework-connectivity-test-defaults"],
srcs: ["**/*.java"],
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index be1e2b2..dc07758 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -1,4 +1,4 @@
-// Copyright (C} 2018 The Android Open Source Project
+// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License"};
// you may not use this file except in compliance with the License.
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
// Sysconfig files
package {
@@ -134,13 +133,6 @@
}
prebuilt_etc {
- name: "privapp_whitelist_com.android.networkstack.tethering",
- sub_dir: "permissions",
- src: "com.android.networkstack.tethering.xml",
- filename_from_src: true,
-}
-
-prebuilt_etc {
name: "privapp_whitelist_com.android.provision",
system_ext_specific: true,
sub_dir: "permissions",
diff --git a/data/etc/com.android.networkstack.tethering.xml b/data/etc/com.android.networkstack.tethering.xml
deleted file mode 100644
index f26a961..0000000
--- a/data/etc/com.android.networkstack.tethering.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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
--->
-
-<permissions>
- <privapp-permissions package="com.android.networkstack.tethering">
- <permission name="android.permission.BLUETOOTH_PRIVILEGED" />
- <permission name="android.permission.MANAGE_USB"/>
- <permission name="android.permission.MODIFY_PHONE_STATE"/>
- <permission name="android.permission.READ_NETWORK_USAGE_HISTORY"/>
- <permission name="android.permission.TETHER_PRIVILEGED"/>
- <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
- <permission name="android.permission.UPDATE_DEVICE_STATS"/>
- </privapp-permissions>
-</permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index fa6b086..82aff60 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -20,13 +20,6 @@
applications that come with the platform
-->
<permissions>
- <privapp-permissions package="android.ext.services">
- <permission name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" />
- <permission name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" />
- <permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
- <permission name="android.permission.INTERACT_ACROSS_USERS" />
- </privapp-permissions>
-
<!-- Needed for Build.getSerial(), which is used to send a unique number for serial, per HUIG. -->
<privapp-permissions package="android.car.usb.handler">
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
@@ -274,6 +267,7 @@
<privapp-permissions package="com.android.server.telecom">
<permission name="android.permission.BIND_CONNECTION_SERVICE"/>
<permission name="android.permission.BIND_INCALL_SERVICE"/>
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
<permission name="android.permission.CALL_PRIVILEGED"/>
<permission name="android.permission.HANDLE_CAR_MODE_CHANGES"/>
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
@@ -393,6 +387,7 @@
<!-- 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,7 +456,11 @@
<!-- 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 needed for CTS test - ConcurrencyTest#testP2pExternalApprover
+ P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. -->
+ <permission name="android.permission.MANAGE_WIFI_AUTO_JOIN" />
<!-- Permission required for CTS test CarrierMessagingServiceWrapperTest -->
<permission name="android.permission.BIND_CARRIER_SERVICES"/>
<!-- Permission required for CTS test - MusicRecognitionManagerTest -->
@@ -519,17 +518,6 @@
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
</privapp-permissions>
- <privapp-permissions package="com.android.traceur">
- <!-- Permissions required to receive BUGREPORT_STARTED intent -->
- <permission name="android.permission.DUMP"/>
- <!-- Permissions required to start/stop tracing -->
- <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
- <!-- Permissions required for quick settings tile -->
- <permission name="android.permission.STATUS_BAR"/>
- <!-- Permissions required to query Betterbug -->
- <permission name="android.permission.QUERY_ALL_PACKAGES"/>
- </privapp-permissions>
-
<privapp-permissions package="com.android.tv">
<permission name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/>
<permission name="android.permission.DVB_DEVICE"/>
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 42e470b..5bfc321 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1611,7 +1611,7 @@
* 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 @@
* 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 9b2effc..0fadae2 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -288,7 +288,7 @@
* 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 cdf746f..f440b69 100644
--- a/identity/java/android/security/identity/IdentityCredential.java
+++ b/identity/java/android/security/identity/IdentityCredential.java
@@ -454,7 +454,8 @@
* @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 @@
* @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 305d0ea..6d56964 100644
--- a/identity/java/android/security/identity/WritableIdentityCredential.java
+++ b/identity/java/android/security/identity/WritableIdentityCredential.java
@@ -59,7 +59,8 @@
* @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 a63ca46..7ab9d76 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 1034847..3d53cfb 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -108,7 +108,7 @@
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 @@
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 @@
}
}
- 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 @@
// 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 30389a29d..54184db 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 e6c1ea8..737ff2b 100644
--- a/keystore/java/android/security/KeyStoreOperation.java
+++ b/keystore/java/android/security/KeyStoreOperation.java
@@ -75,7 +75,7 @@
);
}
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 @@
"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 b85dd74..9c0b46c 100644
--- a/keystore/java/android/security/KeyStoreSecurityLevel.java
+++ b/keystore/java/android/security/KeyStoreSecurityLevel.java
@@ -54,12 +54,12 @@
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 @@
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/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index 2e85b30..31dd10a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -66,6 +66,7 @@
import java.security.UnrecoverableKeyException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
+import java.security.spec.NamedParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.ArrayList;
import java.util.Arrays;
@@ -119,36 +120,42 @@
private static final int RSA_MIN_KEY_SIZE = 512;
private static final int RSA_MAX_KEY_SIZE = 8192;
- private static final Map<String, Integer> SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE =
+ private static final Map<String, Integer> SUPPORTED_EC_CURVE_NAME_TO_SIZE =
new HashMap<String, Integer>();
- private static final List<String> SUPPORTED_EC_NIST_CURVE_NAMES = new ArrayList<String>();
- private static final List<Integer> SUPPORTED_EC_NIST_CURVE_SIZES = new ArrayList<Integer>();
+ private static final List<String> SUPPORTED_EC_CURVE_NAMES = new ArrayList<String>();
+ private static final List<Integer> SUPPORTED_EC_CURVE_SIZES = new ArrayList<Integer>();
+ private static final String CURVE_X_25519 = NamedParameterSpec.X25519.getName();
+ private static final String CURVE_ED_25519 = NamedParameterSpec.ED25519.getName();
+
static {
// Aliases for NIST P-224
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-224", 224);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-224", 224);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp224r1", 224);
// Aliases for NIST P-256
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-256", 256);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("prime256v1", 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-256", 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp256r1", 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("prime256v1", 256);
+ // Aliases for Curve 25519
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put(CURVE_X_25519.toLowerCase(Locale.US), 256);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put(CURVE_ED_25519.toLowerCase(Locale.US), 256);
// Aliases for NIST P-384
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-384", 384);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp384r1", 384);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-384", 384);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp384r1", 384);
// Aliases for NIST P-521
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("p-521", 521);
- SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.put("secp521r1", 521);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("p-521", 521);
+ SUPPORTED_EC_CURVE_NAME_TO_SIZE.put("secp521r1", 521);
- SUPPORTED_EC_NIST_CURVE_NAMES.addAll(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.keySet());
- Collections.sort(SUPPORTED_EC_NIST_CURVE_NAMES);
+ SUPPORTED_EC_CURVE_NAMES.addAll(SUPPORTED_EC_CURVE_NAME_TO_SIZE.keySet());
+ Collections.sort(SUPPORTED_EC_CURVE_NAMES);
- SUPPORTED_EC_NIST_CURVE_SIZES.addAll(
- new HashSet<Integer>(SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.values()));
- Collections.sort(SUPPORTED_EC_NIST_CURVE_SIZES);
+ SUPPORTED_EC_CURVE_SIZES.addAll(
+ new HashSet<Integer>(SUPPORTED_EC_CURVE_NAME_TO_SIZE.values()));
+ Collections.sort(SUPPORTED_EC_CURVE_SIZES);
}
private final int mOriginalKeymasterAlgorithm;
@@ -164,6 +171,7 @@
private int mKeySizeBits;
private SecureRandom mRng;
private KeyDescriptor mAttestKeyDescriptor;
+ private String mEcCurveName;
private int[] mKeymasterPurposes;
private int[] mKeymasterBlockModes;
@@ -177,12 +185,15 @@
mOriginalKeymasterAlgorithm = keymasterAlgorithm;
}
- private @EcCurve int keySize2EcCurve(int keySizeBits)
+ private static @EcCurve int keySizeAndNameToEcCurve(int keySizeBits, String ecCurveName)
throws InvalidAlgorithmParameterException {
switch (keySizeBits) {
case 224:
return EcCurve.P_224;
case 256:
+ if (isCurve25519(ecCurveName)) {
+ return EcCurve.CURVE_25519;
+ }
return EcCurve.P_256;
case 384:
return EcCurve.P_384;
@@ -247,7 +258,8 @@
if (mKeySizeBits == -1) {
mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
}
- checkValidKeySize(keymasterAlgorithm, mKeySizeBits, mSpec.isStrongBoxBacked());
+ checkValidKeySize(keymasterAlgorithm, mKeySizeBits, mSpec.isStrongBoxBacked(),
+ mEcCurveName);
if (spec.getKeystoreAlias() == null) {
throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
@@ -299,6 +311,7 @@
mAttestKeyDescriptor = buildAndCheckAttestKeyDescriptor(spec);
checkAttestKeyPurpose(spec);
+ checkCorrectKeyPurposeForCurve(spec);
success = true;
} finally {
@@ -317,6 +330,42 @@
}
}
+ private void checkCorrectKeyPurposeForCurve(KeyGenParameterSpec spec)
+ throws InvalidAlgorithmParameterException {
+ // Validate the key usage purposes against the curve. x25519 should be
+ // key exchange only, ed25519 signing and attesting.
+
+ if (!isCurve25519(mEcCurveName)) {
+ return;
+ }
+
+ if (mEcCurveName.equalsIgnoreCase(CURVE_X_25519)
+ && spec.getPurposes() != KeyProperties.PURPOSE_AGREE_KEY) {
+ throw new InvalidAlgorithmParameterException(
+ "x25519 may only be used for key agreement.");
+ } else if (mEcCurveName.equalsIgnoreCase(CURVE_ED_25519)
+ && !hasOnlyAllowedPurposeForEd25519(spec.getPurposes())) {
+ throw new InvalidAlgorithmParameterException(
+ "ed25519 may not be used for key agreement.");
+ }
+ }
+
+ private static boolean isCurve25519(String ecCurveName) {
+ if (ecCurveName == null) {
+ return false;
+ }
+ return ecCurveName.equalsIgnoreCase(CURVE_X_25519)
+ || ecCurveName.equalsIgnoreCase(CURVE_ED_25519);
+ }
+
+ private static boolean hasOnlyAllowedPurposeForEd25519(@KeyProperties.PurposeEnum int purpose) {
+ final int allowedPurposes = KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY
+ | KeyProperties.PURPOSE_ATTEST_KEY;
+ boolean hasAllowedPurpose = (purpose & allowedPurposes) != 0;
+ boolean hasDisallowedPurpose = (purpose & ~allowedPurposes) != 0;
+ return hasAllowedPurpose && !hasDisallowedPurpose;
+ }
+
private KeyDescriptor buildAndCheckAttestKeyDescriptor(KeyGenParameterSpec spec)
throws InvalidAlgorithmParameterException {
if (spec.getAttestKeyAlias() != null) {
@@ -473,6 +522,7 @@
mRSAPublicExponent = null;
mRng = null;
mKeyStore = null;
+ mEcCurveName = null;
}
private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
@@ -514,13 +564,13 @@
case KeymasterDefs.KM_ALGORITHM_EC:
if (algSpecificSpec instanceof ECGenParameterSpec) {
ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
- String curveName = ecSpec.getName();
- Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get(
- curveName.toLowerCase(Locale.US));
+ mEcCurveName = ecSpec.getName();
+ final Integer ecSpecKeySizeBits = SUPPORTED_EC_CURVE_NAME_TO_SIZE.get(
+ mEcCurveName.toLowerCase(Locale.US));
if (ecSpecKeySizeBits == null) {
throw new InvalidAlgorithmParameterException(
- "Unsupported EC curve name: " + curveName
- + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
+ "Unsupported EC curve name: " + mEcCurveName
+ + ". Supported: " + SUPPORTED_EC_CURVE_NAMES);
}
if (mKeySizeBits == -1) {
mKeySizeBits = ecSpecKeySizeBits;
@@ -744,7 +794,7 @@
if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
params.add(KeyStore2ParameterUtils.makeEnum(
- Tag.EC_CURVE, keySize2EcCurve(mKeySizeBits)
+ Tag.EC_CURVE, keySizeAndNameToEcCurve(mKeySizeBits, mEcCurveName)
));
}
@@ -864,7 +914,8 @@
private static void checkValidKeySize(
int keymasterAlgorithm,
int keySize,
- boolean isStrongBoxBacked)
+ boolean isStrongBoxBacked,
+ String mEcCurveName)
throws InvalidAlgorithmParameterException {
switch (keymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_EC:
@@ -873,9 +924,13 @@
"Unsupported StrongBox EC key size: "
+ keySize + " bits. Supported: 256");
}
- if (!SUPPORTED_EC_NIST_CURVE_SIZES.contains(keySize)) {
+ if (isStrongBoxBacked && isCurve25519(mEcCurveName)) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported StrongBox EC: " + mEcCurveName);
+ }
+ if (!SUPPORTED_EC_CURVE_SIZES.contains(keySize)) {
throw new InvalidAlgorithmParameterException("Unsupported EC key size: "
- + keySize + " bits. Supported: " + SUPPORTED_EC_NIST_CURVE_SIZES);
+ + keySize + " bits. Supported: " + SUPPORTED_EC_CURVE_SIZES);
}
break;
case KeymasterDefs.KM_ALGORITHM_RSA:
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index 72a145f..358104f 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -66,6 +66,11 @@
private static final String DESEDE_SYSTEM_PROPERTY =
"ro.hardware.keystore_desede";
+ // Conscrypt returns the Ed25519 OID as the JCA key algorithm.
+ private static final String ED25519_OID = "1.3.101.112";
+ // Conscrypt returns "XDH" as the X25519 JCA key algorithm.
+ private static final String X25519_ALIAS = "XDH";
+
/** @hide **/
public AndroidKeyStoreProvider() {
super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
@@ -78,10 +83,16 @@
// java.security.KeyPairGenerator
put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC");
put("KeyPairGenerator.RSA", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
+ put("KeyPairGenerator." + X25519_ALIAS,
+ PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
+ put("KeyPairGenerator." + ED25519_OID,
+ PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA");
// java.security.KeyFactory
putKeyFactoryImpl("EC");
putKeyFactoryImpl("RSA");
+ putKeyFactoryImpl(X25519_ALIAS);
+ putKeyFactoryImpl(ED25519_OID);
// javax.crypto.KeyGenerator
put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES");
@@ -219,12 +230,17 @@
KeyStoreSecurityLevel securityLevel = iSecurityLevel;
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
-
return new AndroidKeyStoreECPublicKey(descriptor, metadata,
iSecurityLevel, (ECPublicKey) publicKey);
} else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(jcaKeyAlgorithm)) {
return new AndroidKeyStoreRSAPublicKey(descriptor, metadata,
iSecurityLevel, (RSAPublicKey) publicKey);
+ } else if (ED25519_OID.equalsIgnoreCase(jcaKeyAlgorithm)) {
+ //TODO(b/214203951) missing classes in conscrypt
+ throw new ProviderException("Curve " + ED25519_OID + " not supported yet");
+ } else if (X25519_ALIAS.equalsIgnoreCase(jcaKeyAlgorithm)) {
+ //TODO(b/214203951) missing classes in conscrypt
+ throw new ProviderException("Curve " + X25519_ALIAS + " not supported yet");
} else {
throw new ProviderException("Unsupported Android Keystore public key algorithm: "
+ jcaKeyAlgorithm);
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 0000000..31c7422
--- /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 d17c328..8150e78 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -686,6 +686,12 @@
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/androidfw/tests/BackupHelpers_test.cpp b/libs/androidfw/tests/BackupHelpers_test.cpp
index 86b7fb3..c2fcb69 100644
--- a/libs/androidfw/tests/BackupHelpers_test.cpp
+++ b/libs/androidfw/tests/BackupHelpers_test.cpp
@@ -50,7 +50,7 @@
TEST_F(BackupHelpersTest, WriteTarFileWithSizeGreaterThan2GB) {
TemporaryFile tf;
// Allocate a 2 GB file.
- off64_t fileSize = 2ll * 1024ll * 1024ll * 1024ll + 512ll;
+ off64_t fileSize = 2LL * 1024LL * 1024LL * 1024LL + 512LL;
ASSERT_EQ(0, posix_fallocate64(tf.fd, 0, fileSize));
off64_t tarSize = 0;
int err = write_tarfile(/* packageName */ String8("test-pkg"), /* domain */ String8(""), /* rootpath */ String8(""), /* filePath */ String8(tf.path), /* outSize */ &tarSize, /* writer */ NULL);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2fed468..00561be 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -287,7 +287,7 @@
};
// 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/media/Android.bp b/media/Android.bp
index 1b7bef5..b7c3a9c 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -100,6 +100,11 @@
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 a186566..3edb101 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -177,6 +177,11 @@
*/
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 @@
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 @@
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 @@
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 @@
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 @@
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 ebe0882..9211c53 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -90,7 +90,8 @@
* {@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 b7e8c8c..ce2bccf 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5404,6 +5404,10 @@
*/
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 @@
* @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 143b11f..33b877c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -982,6 +982,8 @@
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 @@
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 @@
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 @@
/** @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 @@
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
similarity index 93%
rename from media/java/android/media/BtProfileConnectionInfo.aidl
rename to media/java/android/media/BluetoothProfileConnectionInfo.aidl
index 047f06b..0617084 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
similarity index 65%
rename from media/java/android/media/BtProfileConnectionInfo.java
rename to media/java/android/media/BluetoothProfileConnectionInfo.java
index 88b9777..c148846 100644
--- a/media/java/android/media/BtProfileConnectionInfo.java
+++ b/media/java/android/media/BluetoothProfileConnectionInfo.java
@@ -26,15 +26,14 @@
* {@hide}
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-public final class BtProfileConnectionInfo implements Parcelable {
-
+public final class BluetoothProfileConnectionInfo implements Parcelable {
private final int mProfile;
private final boolean mSupprNoisy;
private final int mVolume;
private final boolean mIsLeOutput;
- private BtProfileConnectionInfo(int profile, boolean suppressNoisyIntent, int volume,
- boolean isLeOutput) {
+ private BluetoothProfileConnectionInfo(int profile, boolean suppressNoisyIntent,
+ int volume, boolean isLeOutput) {
mProfile = profile;
mSupprNoisy = suppressNoisyIntent;
mVolume = volume;
@@ -45,21 +44,21 @@
* Constructor used by BtHelper when a profile is connected
* {@hide}
*/
- public BtProfileConnectionInfo(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];
}
};
@@ -84,10 +83,10 @@
*
* @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);
}
/**
@@ -96,8 +95,8 @@
*
* @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);
}
/**
@@ -106,9 +105,10 @@
* @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);
}
/**
@@ -119,10 +119,10 @@
*
* @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);
}
/**
@@ -136,7 +136,7 @@
* @return {@code true} if {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be
* sent
*/
- public boolean getSuppressNoisyIntent() {
+ public boolean isSuppressNoisyIntent() {
return mSupprNoisy;
}
@@ -153,7 +153,7 @@
* @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 5ff56f9..d5a2d07 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -24,7 +24,7 @@
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 @@
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/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 1da41fb..33bc846 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -407,7 +407,7 @@
/**
* Get the session owner's package name.
*
- * @return The package name of of the session owner.
+ * @return The package name of the session owner.
*/
public String getPackageName() {
if (mPackageName == null) {
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index d8f48c2..20d711c 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -103,6 +103,7 @@
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 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 @@
}
mHostType = "";
mSkipThumbForHost = false;
+ mHostIsWindows = false;
}
@VisibleForNative
@@ -736,10 +738,12 @@
: 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 88c32a3..a3754e90 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -19,6 +19,8 @@
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 @@
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 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 0bede0d..e9426cf 100644
--- a/media/java/android/mtp/MtpStorageManager.java
+++ b/media/java/android/mtp/MtpStorageManager.java
@@ -18,7 +18,11 @@
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.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 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 @@
* @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/BtProfileConnectionInfoTest.java
deleted file mode 100644
index fd66d3b..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.mediaframeworktest.unit;
-
-import static org.junit.Assert.assertEquals;
-
-import android.bluetooth.BluetoothProfile;
-import android.media.BtProfileConnectionInfo;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class BtProfileConnectionInfoTest {
-
- @Test
- public void testCoverageA2dp() {
- final boolean supprNoisy = false;
- final int volume = 42;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpInfo(supprNoisy, volume);
- assertEquals(info.getProfile(), BluetoothProfile.A2DP);
- assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
- assertEquals(info.getVolume(), volume);
- }
-
- @Test
- public void testCoverageA2dpSink() {
- final int volume = 42;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpSinkInfo(volume);
- assertEquals(info.getProfile(), BluetoothProfile.A2DP_SINK);
- assertEquals(info.getVolume(), volume);
- }
-
- @Test
- public void testCoveragehearingAid() {
- final boolean supprNoisy = true;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.hearingAidInfo(supprNoisy);
- assertEquals(info.getProfile(), BluetoothProfile.HEARING_AID);
- assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
- }
-
- @Test
- public void testCoverageLeAudio() {
- final boolean supprNoisy = false;
- final boolean isLeOutput = true;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.leAudio(supprNoisy,
- isLeOutput);
- assertEquals(info.getProfile(), BluetoothProfile.LE_AUDIO);
- assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
- assertEquals(info.getIsLeOutput(), isLeOutput);
- }
-}
-
diff --git a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
index fdf6582..eb357f6 100644
--- a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
+++ b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
@@ -159,10 +159,11 @@
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/OWNERS b/native/android/OWNERS
index 8b35f8d..3fb524d 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,14 +1,23 @@
-jreck@google.com
+jreck@google.com #{LAST_RESORT_SUGGESTION}
+# General NDK API reviewers
+per-file libandroid.map.txt = danalbert@google.com, etalvala@google.com, michaelwr@google.com
+per-file libandroid.map.txt = jreck@google.com, zyy@google.com
+
+# Networking
per-file libandroid_net.map.txt, net.c = set noparent
per-file libandroid_net.map.txt, net.c = jchalard@google.com, junyulai@google.com
per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
+
+# Fonts
per-file system_fonts.cpp = file:/graphics/java/android/graphics/fonts/OWNERS
+# Window manager
per-file native_window_jni.cpp = file:/services/core/java/com/android/server/wm/OWNERS
per-file native_activity.cpp = file:/services/core/java/com/android/server/wm/OWNERS
per-file surface_control.cpp = file:/services/core/java/com/android/server/wm/OWNERS
+# Graphics
per-file choreographer.cpp = file:/graphics/java/android/graphics/OWNERS
per-file hardware_buffer_jni.cpp = file:/graphics/java/android/graphics/OWNERS
per-file native_window_jni.cpp = file:/graphics/java/android/graphics/OWNERS
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index f33e118..2201753 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -300,6 +300,9 @@
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/aidl/vts/functional/config/Android.bp b/omapi/aidl/vts/functional/config/Android.bp
new file mode 100644
index 0000000..7c08257
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/Android.bp
@@ -0,0 +1,26 @@
+//
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+xsd_config {
+ name: "omapi_uuid_map_config",
+ srcs: ["omapi_uuid_map_config.xsd"],
+ api_dir: "schema",
+ package_name: "omapi.uuid.map.config",
+}
diff --git a/omapi/aidl/vts/functional/config/omapi_uuid_map_config.xsd b/omapi/aidl/vts/functional/config/omapi_uuid_map_config.xsd
new file mode 100644
index 0000000..ffeb7a0
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/omapi_uuid_map_config.xsd
@@ -0,0 +1,40 @@
+<?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.
+-->
+<xs:schema version="2.0"
+ attributeFormDefault="unqualified"
+ elementFormDefault="qualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:element name="ref_do">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="uuid_ref_do" maxOccurs="unbounded" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="uids">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element type="xs:short" name="uid" maxOccurs="unbounded" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element type="xs:string" name="uuid"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/omapi/aidl/vts/functional/config/schema/current.txt b/omapi/aidl/vts/functional/config/schema/current.txt
new file mode 100644
index 0000000..c2e930b
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/schema/current.txt
@@ -0,0 +1,30 @@
+// Signature format: 2.0
+package omapi.uuid.map.config {
+
+ public class RefDo {
+ ctor public RefDo();
+ method public java.util.List<omapi.uuid.map.config.RefDo.UuidRefDo> getUuid_ref_do();
+ }
+
+ public static class RefDo.UuidRefDo {
+ ctor public RefDo.UuidRefDo();
+ method public omapi.uuid.map.config.RefDo.UuidRefDo.Uids getUids();
+ method public String getUuid();
+ method public void setUids(omapi.uuid.map.config.RefDo.UuidRefDo.Uids);
+ method public void setUuid(String);
+ }
+
+ public static class RefDo.UuidRefDo.Uids {
+ ctor public RefDo.UuidRefDo.Uids();
+ method public java.util.List<java.lang.Short> getUid();
+ }
+
+ public class XmlParser {
+ ctor public XmlParser();
+ method public static omapi.uuid.map.config.RefDo read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ }
+
+}
+
diff --git a/omapi/aidl/vts/functional/config/schema/last_current.txt b/omapi/aidl/vts/functional/config/schema/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/schema/last_current.txt
diff --git a/omapi/aidl/vts/functional/config/schema/last_removed.txt b/omapi/aidl/vts/functional/config/schema/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omapi/aidl/vts/functional/config/schema/last_removed.txt
diff --git a/apex/media/framework/api/removed.txt b/omapi/aidl/vts/functional/config/schema/removed.txt
similarity index 100%
rename from apex/media/framework/api/removed.txt
rename to omapi/aidl/vts/functional/config/schema/removed.txt
diff --git a/omapi/aidl/vts/functional/omapi/Android.bp b/omapi/aidl/vts/functional/omapi/Android.bp
index c3ab8d1..c41479f 100644
--- a/omapi/aidl/vts/functional/omapi/Android.bp
+++ b/omapi/aidl/vts/functional/omapi/Android.bp
@@ -39,6 +39,11 @@
static_libs: [
"VtsHalHidlTargetTestBase",
"android.se.omapi-V1-ndk",
+ "android.hardware.audio.common.test.utility",
+ "libxml2",
+ ],
+ data: [
+ ":omapi_uuid_map_config",
],
cflags: [
"-O0",
@@ -51,4 +56,5 @@
"general-tests",
"vts",
],
+ test_config: "VtsHalOmapiSeServiceV1_TargetTest.xml",
}
diff --git a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
index 319cb7e..5303651 100644
--- a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
+++ b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
@@ -32,6 +32,7 @@
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <utils/String16.h>
+#include "utility/ValidateXml.h"
using namespace std;
using namespace ::testing;
@@ -176,6 +177,25 @@
return (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str()));
}
+ std::optional<std::string> getUuidMappingFile() {
+ char value[PROPERTY_VALUE_MAX] = {0};
+ int len = property_get("ro.boot.product.hardware.sku", value, "config");
+ std::string uuidMappingConfigFile = UUID_MAPPING_CONFIG_PREFIX
+ + std::string(value, len)
+ + UUID_MAPPING_CONFIG_EXT;
+ std::string uuidMapConfigPath;
+ // Search in predefined folders
+ for (auto path : UUID_MAPPING_CONFIG_PATHS) {
+ uuidMapConfigPath = path + uuidMappingConfigFile;
+ auto confFile = fopen(uuidMapConfigPath.c_str(), "r");
+ if (confFile) {
+ fclose(confFile);
+ return uuidMapConfigPath;
+ }
+ }
+ return std::optional<std::string>();
+ }
+
void SetUp() override {
LOG(INFO) << "get OMAPI service with name:" << GetParam();
::ndk::SpAIBinder ks2Binder(AServiceManager_getService(GetParam().c_str()));
@@ -300,6 +320,10 @@
std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
mVSReaders = {};
+
+ std::string UUID_MAPPING_CONFIG_PREFIX = "hal_uuid_map_";
+ std::string UUID_MAPPING_CONFIG_EXT = ".xml";
+ std::string UUID_MAPPING_CONFIG_PATHS[3] = {"/odm/etc/", "/vendor/etc/", "/etc/"};
};
/** Tests getReaders API */
@@ -600,6 +624,14 @@
}
}
+TEST_P(OMAPISEServiceHalTest, TestUuidMappingConfig) {
+ constexpr const char* xsd = "/data/local/tmp/omapi_uuid_map_config.xsd";
+ auto uuidMappingFile = getUuidMappingFile();
+ ASSERT_TRUE(uuidMappingFile.has_value()) << "Unable to determine UUID mapping config file path";
+ LOG(INFO) << "UUID Mapping config file: " << uuidMappingFile.value();
+ EXPECT_VALID_XML(uuidMappingFile->c_str(), xsd);
+}
+
INSTANTIATE_TEST_SUITE_P(PerInstance, OMAPISEServiceHalTest,
testing::ValuesIn(::android::getAidlHalInstanceNames(
aidl::android::se::omapi::ISecureElementService::descriptor)),
diff --git a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.xml b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.xml
new file mode 100644
index 0000000..3ee0414
--- /dev/null
+++ b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<configuration description="Runs VtsHalOmapiSeServiceV1_TargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push"
+ value="omapi_uuid_map_config.xsd->/data/local/tmp/omapi_uuid_map_config.xsd" />
+ <option name="push"
+ value="VtsHalOmapiSeServiceV1_TargetTest->/data/local/tmp/VtsHalOmapiSeServiceV1_TargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalOmapiSeServiceV1_TargetTest" />
+ </test>
+</configuration>
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 223bdcdd..6652780 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -39,7 +39,6 @@
"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 @@
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",
@@ -159,8 +158,6 @@
name: "framework-connectivity-tiramisu-sources",
srcs: [
":framework-connectivity-ethernet-sources",
- ":framework-connectivity-ipsec-sources",
- ":framework-connectivity-netstats-sources",
],
visibility: ["//frameworks/base"],
}
@@ -168,6 +165,8 @@
filegroup {
name: "framework-connectivity-tiramisu-updatable-sources",
srcs: [
+ ":framework-connectivity-ipsec-sources",
+ ":framework-connectivity-netstats-sources",
":framework-connectivity-nsd-sources",
":framework-connectivity-tiramisu-internal-sources",
],
@@ -176,3 +175,31 @@
"//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: [
+ "libandroid",
+ "liblog",
+ "libnativehelper",
+ ],
+ stl: "none",
+ apex_available: [
+ "com.android.tethering",
+ ],
+}
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 0000000..f3c58b1
--- /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 0000000..1fb42c6
--- /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 5ce7e59..ca080ce 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -27,7 +27,6 @@
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
-import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.app.usage.NetworkStats.Bucket;
import android.compat.annotation.UnsupportedAppUsage;
@@ -192,9 +191,13 @@
}
}
- /** @hide */
+ /**
+ * Set poll force flag to indicate that calling any subsequent query method will force a stats
+ * poll.
+ * @hide
+ */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @TestApi
+ @SystemApi(client = MODULE_LIBRARIES)
public void setPollForce(boolean pollForce) {
if (pollForce) {
mFlags |= FLAG_POLL_FORCE;
@@ -696,7 +699,9 @@
* @hide
*/
@SystemApi
- @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
@NonNull public android.net.NetworkStats getMobileUidStats() {
try {
return mService.getUidStatsForTransport(TRANSPORT_CELLULAR);
@@ -720,7 +725,9 @@
* @hide
*/
@SystemApi
- @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
@NonNull public android.net.NetworkStats getWifiUidStats() {
try {
return mService.getUidStatsForTransport(TRANSPORT_WIFI);
@@ -737,8 +744,9 @@
* {@link #unregisterUsageCallback} is called.
*
* @param template Template used to match networks. See {@link NetworkTemplate}.
- * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower
- * than 2MiB will be clamped for non-privileged callers.
+ * @param thresholdBytes Threshold in bytes to be notified on. Provided values lower than 2MiB
+ * will be clamped for callers except callers with the NETWORK_STACK
+ * permission.
* @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.
@@ -747,6 +755,9 @@
* @hide
*/
@SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK}, conditional = true)
public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes,
@NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) {
Objects.requireNonNull(template, "NetworkTemplate cannot be null");
diff --git a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
index 630f902e..9bffbfb 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java
@@ -18,6 +18,7 @@
import android.annotation.SystemApi;
import android.app.SystemServiceRegistry;
+import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
@@ -48,5 +49,24 @@
return new NsdManager(context, service);
}
);
+
+ SystemServiceRegistry.registerContextAwareService(
+ Context.IPSEC_SERVICE,
+ IpSecManager.class,
+ (context, serviceBinder) -> {
+ IIpSecService service = IIpSecService.Stub.asInterface(serviceBinder);
+ return new IpSecManager(context, service);
+ }
+ );
+
+ SystemServiceRegistry.registerContextAwareService(
+ Context.NETWORK_STATS_SERVICE,
+ NetworkStatsManager.class,
+ (context, serviceBinder) -> {
+ INetworkStatsService service =
+ INetworkStatsService.Stub.asInterface(serviceBinder);
+ return new NetworkStatsManager(context, service);
+ }
+ );
}
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index ece54df..72243f9 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -16,28 +16,34 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
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;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
/**
- * A class representing the IP configuration of the Ethernet network.
+ * A class that manages and configures Ethernet interfaces.
*
* @hide
*/
@@ -52,11 +58,13 @@
private final IEthernetServiceListener.Stub mServiceListener =
new IEthernetServiceListener.Stub() {
@Override
- public void onAvailabilityChanged(String iface, boolean isAvailable) {
+ public void onInterfaceStateChanged(String iface, int state, int role,
+ IpConfiguration configuration) {
synchronized (mListeners) {
for (ListenerInfo li : mListeners) {
li.executor.execute(() ->
- li.listener.onAvailabilityChanged(iface, isAvailable));
+ li.listener.onInterfaceStateChanged(iface, state, role,
+ configuration));
}
}
}
@@ -66,19 +74,93 @@
@NonNull
public final Executor executor;
@NonNull
- public final Listener listener;
+ public final InterfaceStateListener listener;
- private ListenerInfo(@NonNull Executor executor, @NonNull Listener listener) {
+ private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) {
this.executor = executor;
this.listener = listener;
}
}
/**
- * A listener interface to receive notification on changes in Ethernet.
+ * The interface is absent.
* @hide
*/
- public interface Listener {
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int STATE_ABSENT = 0;
+
+ /**
+ * The interface is present but link is down.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int STATE_LINK_DOWN = 1;
+
+ /**
+ * The interface is present and link is up.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int STATE_LINK_UP = 2;
+
+ /** @hide */
+ @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InterfaceState {}
+
+ /**
+ * The interface currently does not have any specific role.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int ROLE_NONE = 0;
+
+ /**
+ * The interface is in client mode (e.g., connected to the Internet).
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int ROLE_CLIENT = 1;
+
+ /**
+ * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int ROLE_SERVER = 2;
+
+ /** @hide */
+ @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Role {}
+
+ /**
+ * A listener that receives notifications about the state of Ethernet interfaces on the system.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public interface InterfaceStateListener {
+ /**
+ * Called when an Ethernet interface changes state.
+ *
+ * @param iface the name of the interface.
+ * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
+ * interface was removed.
+ * @param role whether the interface is in client mode or server mode.
+ * @param configuration the current IP configuration of the interface.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
+ @Role int role, @Nullable IpConfiguration configuration);
+ }
+
+ /**
+ * A listener interface to receive notification on changes in Ethernet.
+ * This has never been a supported API. Use {@link InterfaceStateListener} instead.
+ * @hide
+ */
+ public interface Listener extends InterfaceStateListener {
/**
* Called when Ethernet port's availability is changed.
* @param iface Ethernet interface name
@@ -87,6 +169,13 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
void onAvailabilityChanged(String iface, boolean isAvailable);
+
+ /** Default implementation for backwards compatibility. Only calls the legacy listener. */
+ default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
+ @Role int role, @Nullable IpConfiguration configuration) {
+ onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
+ }
+
}
/**
@@ -119,7 +208,7 @@
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void setConfiguration(String iface, IpConfiguration config) {
+ public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
try {
mService.setConfiguration(iface, config);
} catch (RemoteException e) {
@@ -153,9 +242,8 @@
/**
* Adds a listener.
+ * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
*
- * Consider using {@link #addListener(Listener, Executor)} instead: this method uses a default
- * executor that may have higher latency than a provided executor.
* @param listener A {@link Listener} to add.
* @throws IllegalArgumentException If the listener is null.
* @hide
@@ -167,6 +255,8 @@
/**
* Adds a listener.
+ * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
+ *
* @param listener A {@link Listener} to add.
* @param executor Executor to run callbacks on.
* @throws IllegalArgumentException If the listener or executor is null.
@@ -174,6 +264,28 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
+ addInterfaceStateListener(executor, listener);
+ }
+
+ /**
+ * Listen to changes in the state of Ethernet interfaces.
+ *
+ * Adds a listener to receive notification for any state change of all existing Ethernet
+ * interfaces.
+ * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
+ * existing interfaces upon adding a listener. The same method will be called on the
+ * listener every time any of the interface changes state. In particular, if an
+ * interface is removed, it will be called with state {@link #STATE_ABSENT}.
+ * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
+ *
+ * @param executor Executor to run callbacks on.
+ * @param listener A {@link Listener} to add.
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ @SystemApi(client = MODULE_LIBRARIES)
+ public void addInterfaceStateListener(@NonNull Executor executor,
+ @NonNull InterfaceStateListener listener) {
if (listener == null || executor == null) {
throw new NullPointerException("listener and executor must not be null");
}
@@ -204,15 +316,13 @@
/**
* Removes a listener.
+ *
* @param listener A {@link Listener} to remove.
- * @throws IllegalArgumentException If the listener is null.
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public void removeListener(@NonNull Listener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener must not be null");
- }
+ @SystemApi(client = MODULE_LIBRARIES)
+ public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
+ Objects.requireNonNull(listener);
synchronized (mListeners) {
mListeners.removeIf(l -> l.listener == listener);
if (mListeners.isEmpty()) {
@@ -226,12 +336,26 @@
}
/**
+ * Removes a listener.
+ * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
+ * @param listener A {@link Listener} to remove.
+ * @hide
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public void removeListener(@NonNull Listener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ removeInterfaceStateListener(listener);
+ }
+
+ /**
* Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
* as Ethernet interfaces. The effects of this method apply to any test interfaces that are
* already present on the system.
* @hide
*/
- @TestApi
+ @SystemApi(client = MODULE_LIBRARIES)
public void setIncludeTestInterfaces(boolean include) {
try {
mService.setIncludeTestInterfaces(include);
@@ -320,15 +444,15 @@
}
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 +462,14 @@
@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 +482,43 @@
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 +528,34 @@
}
}
- 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 +565,33 @@
}
}
- 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
similarity index 93%
rename from packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
index dcce706..adf9e5a 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/EthernetNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
new file mode 100644
index 0000000..a69cc55
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
@@ -0,0 +1,73 @@
+/*
+ * 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.net;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/** @hide */
+@SystemApi
+public final class EthernetNetworkManagementException
+ extends RuntimeException implements Parcelable {
+
+ /* @hide */
+ public EthernetNetworkManagementException(@NonNull final String errorMessage) {
+ super(errorMessage);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getMessage());
+ }
+
+ @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(getMessage());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<EthernetNetworkManagementException> CREATOR =
+ new Parcelable.Creator<EthernetNetworkManagementException>() {
+ @Override
+ public EthernetNetworkManagementException[] newArray(int size) {
+ return new EthernetNetworkManagementException[size];
+ }
+
+ @Override
+ public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) {
+ return new EthernetNetworkManagementException(source.readString());
+ }
+ };
+}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
index 925d12b..e4d6e24 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -29,9 +28,7 @@
* A {@link NetworkSpecifier} used to identify ethernet interfaces.
*
* @see EthernetManager
- * @hide
*/
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable {
/**
@@ -61,6 +58,7 @@
return mInterfaceName;
}
+ /** @hide */
@Override
public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) {
return equals(other);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
similarity index 93%
rename from packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
index da00cb9..debc348 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/EthernetNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
new file mode 100644
index 0000000..a626971
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/** @hide */
+@SystemApi
+public final class EthernetNetworkUpdateRequest implements Parcelable {
+ @NonNull
+ private final IpConfiguration mIpConfig;
+ @NonNull
+ private final NetworkCapabilities mNetworkCapabilities;
+
+ @NonNull
+ public IpConfiguration getIpConfiguration() {
+ return new IpConfiguration(mIpConfig);
+ }
+
+ @NonNull
+ public NetworkCapabilities getNetworkCapabilities() {
+ return new NetworkCapabilities(mNetworkCapabilities);
+ }
+
+ private EthernetNetworkUpdateRequest(@NonNull final IpConfiguration ipConfig,
+ @NonNull final NetworkCapabilities networkCapabilities) {
+ Objects.requireNonNull(ipConfig);
+ Objects.requireNonNull(networkCapabilities);
+ mIpConfig = new IpConfiguration(ipConfig);
+ mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
+ }
+
+ private EthernetNetworkUpdateRequest(@NonNull final Parcel source) {
+ Objects.requireNonNull(source);
+ mIpConfig = IpConfiguration.CREATOR.createFromParcel(source);
+ mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
+ }
+
+ /**
+ * Builder used to create {@link EthernetNetworkUpdateRequest} objects.
+ */
+ public static final class Builder {
+ @Nullable
+ private IpConfiguration mBuilderIpConfig;
+ @Nullable
+ private NetworkCapabilities mBuilderNetworkCapabilities;
+
+ public Builder(){}
+
+ /**
+ * Constructor to populate the builder's values with an already built
+ * {@link EthernetNetworkUpdateRequest}.
+ * @param request the {@link EthernetNetworkUpdateRequest} to populate with.
+ */
+ public Builder(@NonNull final EthernetNetworkUpdateRequest request) {
+ Objects.requireNonNull(request);
+ mBuilderIpConfig = new IpConfiguration(request.mIpConfig);
+ mBuilderNetworkCapabilities = new NetworkCapabilities(request.mNetworkCapabilities);
+ }
+
+ /**
+ * Set the {@link IpConfiguration} to be used with the {@code Builder}.
+ * @param ipConfig the {@link IpConfiguration} to set.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public Builder setIpConfiguration(@NonNull final IpConfiguration ipConfig) {
+ Objects.requireNonNull(ipConfig);
+ mBuilderIpConfig = new IpConfiguration(ipConfig);
+ return this;
+ }
+
+ /**
+ * Set the {@link NetworkCapabilities} to be used with the {@code Builder}.
+ * @param nc the {@link NetworkCapabilities} to set.
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public Builder setNetworkCapabilities(@NonNull final NetworkCapabilities nc) {
+ Objects.requireNonNull(nc);
+ mBuilderNetworkCapabilities = new NetworkCapabilities(nc);
+ return this;
+ }
+
+ /**
+ * Build {@link EthernetNetworkUpdateRequest} return the current update request.
+ */
+ @NonNull
+ public EthernetNetworkUpdateRequest build() {
+ return new EthernetNetworkUpdateRequest(mBuilderIpConfig, mBuilderNetworkCapabilities);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "EthernetNetworkUpdateRequest{"
+ + "mIpConfig=" + mIpConfig
+ + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o;
+
+ return Objects.equals(that.getIpConfiguration(), mIpConfig)
+ && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIpConfig, mNetworkCapabilities);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ mIpConfig.writeToParcel(dest, flags);
+ mNetworkCapabilities.writeToParcel(dest, flags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<EthernetNetworkUpdateRequest> CREATOR =
+ new Parcelable.Creator<EthernetNetworkUpdateRequest>() {
+ @Override
+ public EthernetNetworkUpdateRequest[] newArray(int size) {
+ return new EthernetNetworkUpdateRequest[size];
+ }
+
+ @Override
+ 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 e688bea..544d02b 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 @@
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 @@
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
similarity index 80%
rename from packages/ConnectivityT/framework-t/src/android/net/IInternalNetworkManagementListener.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
index 69cde3b..93edccf 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/IEthernetServiceListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
index 782fa19..6d2ba03 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetServiceListener.aidl
@@ -16,8 +16,11 @@
package android.net;
+import android.net.IpConfiguration;
+
/** @hide */
oneway interface IEthernetServiceListener
{
- void onAvailabilityChanged(String iface, boolean isAvailable);
+ void onInterfaceStateChanged(String iface, int state, int role,
+ in IpConfiguration configuration);
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java
deleted file mode 100644
index 7f4e403..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkManagementException.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.net;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public final class InternalNetworkManagementException
- extends RuntimeException implements Parcelable {
-
- /* @hide */
- public InternalNetworkManagementException(@NonNull final Throwable t) {
- super(t);
- }
-
- private InternalNetworkManagementException(@NonNull final Parcel source) {
- super(source.readString());
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(getCause().getMessage());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public static final Parcelable.Creator<InternalNetworkManagementException> CREATOR =
- new Parcelable.Creator<InternalNetworkManagementException>() {
- @Override
- public InternalNetworkManagementException[] newArray(int size) {
- return new InternalNetworkManagementException[size];
- }
-
- @Override
- public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) {
- return new InternalNetworkManagementException(source);
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java
deleted file mode 100644
index f42c4b7..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/InternalNetworkUpdateRequest.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.net;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/** @hide */
-public final class InternalNetworkUpdateRequest implements Parcelable {
- @NonNull
- private final StaticIpConfiguration mIpConfig;
- @NonNull
- private final NetworkCapabilities mNetworkCapabilities;
-
- @NonNull
- public StaticIpConfiguration getIpConfig() {
- return new StaticIpConfiguration(mIpConfig);
- }
-
- @NonNull
- public NetworkCapabilities getNetworkCapabilities() {
- return new NetworkCapabilities(mNetworkCapabilities);
- }
-
- /** @hide */
- public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
- @NonNull final NetworkCapabilities networkCapabilities) {
- Objects.requireNonNull(ipConfig);
- Objects.requireNonNull(networkCapabilities);
- mIpConfig = new StaticIpConfiguration(ipConfig);
- mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
- }
-
- private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
- Objects.requireNonNull(source);
- mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source);
- mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
- }
-
- @Override
- public String toString() {
- return "InternalNetworkUpdateRequest{"
- + "mIpConfig=" + mIpConfig
- + ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o;
-
- return Objects.equals(that.getIpConfig(), mIpConfig)
- && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mIpConfig, mNetworkCapabilities);
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- mIpConfig.writeToParcel(dest, flags);
- mNetworkCapabilities.writeToParcel(dest, flags);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public static final Parcelable.Creator<InternalNetworkUpdateRequest> CREATOR =
- new Parcelable.Creator<InternalNetworkUpdateRequest>() {
- @Override
- public InternalNetworkUpdateRequest[] newArray(int size) {
- return new InternalNetworkUpdateRequest[size];
- }
-
- @Override
- public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
- return new InternalNetworkUpdateRequest(source);
- }
- };
-}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
index a423783..9cb0947 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
@@ -61,7 +61,7 @@
* Internet Protocol</a>
*/
@SystemService(Context.IPSEC_SERVICE)
-public final class IpSecManager {
+public class IpSecManager {
private static final String TAG = "IpSecManager";
/**
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
index 56faa52..a48f94b 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
@@ -20,6 +20,7 @@
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -86,6 +87,7 @@
final int mType;
final int mRatType;
+ final int mSubId;
final String mSubscriberId;
final String mWifiNetworkKey;
final boolean mRoaming;
@@ -96,7 +98,7 @@
/** @hide */
public NetworkIdentity(
int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
- boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged) {
+ boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged, int subId) {
mType = type;
mRatType = ratType;
mSubscriberId = subscriberId;
@@ -105,12 +107,13 @@
mMetered = metered;
mDefaultNetwork = defaultNetwork;
mOemManaged = oemManaged;
+ mSubId = subId;
}
@Override
public int hashCode() {
return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
- mDefaultNetwork, mOemManaged);
+ mDefaultNetwork, mOemManaged, mSubId);
}
@Override
@@ -122,7 +125,8 @@
&& Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
&& mMetered == ident.mMetered
&& mDefaultNetwork == ident.mDefaultNetwork
- && mOemManaged == ident.mOemManaged;
+ && mOemManaged == ident.mOemManaged
+ && mSubId == ident.mSubId;
}
return false;
}
@@ -150,6 +154,7 @@
builder.append(", metered=").append(mMetered);
builder.append(", defaultNetwork=").append(mDefaultNetwork);
builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
+ builder.append(", subId=").append(mSubId);
return builder.append("}").toString();
}
@@ -184,14 +189,14 @@
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
- proto.write(NetworkIdentityProto.TYPE, mType);
+ proto.write(NetworkIdentityProto.TYPE_FIELD_NUMBER, mType);
// TODO: dump mRatType as well.
- proto.write(NetworkIdentityProto.ROAMING, mRoaming);
- proto.write(NetworkIdentityProto.METERED, mMetered);
- proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork);
- proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged);
+ proto.write(NetworkIdentityProto.ROAMING_FIELD_NUMBER, mRoaming);
+ proto.write(NetworkIdentityProto.METERED_FIELD_NUMBER, mMetered);
+ proto.write(NetworkIdentityProto.DEFAULT_NETWORK_FIELD_NUMBER, mDefaultNetwork);
+ proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK_FIELD_NUMBER, mOemManaged);
proto.end(start);
}
@@ -256,6 +261,11 @@
return mOemManaged;
}
+ /** Get the SubId of this instance. */
+ public int getSubId() {
+ return mSubId;
+ }
+
/**
* Assemble a {@link NetworkIdentity} from the passed arguments.
*
@@ -276,7 +286,8 @@
public static NetworkIdentity buildNetworkIdentity(Context context,
@NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) {
final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
- .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork);
+ .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork)
+ .setSubId(snapshot.getSubId());
if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
builder.setRatType(ratType);
}
@@ -325,6 +336,9 @@
if (res == 0) {
res = Integer.compare(left.mOemManaged, right.mOemManaged);
}
+ if (res == 0) {
+ res = Integer.compare(left.mSubId, right.mSubId);
+ }
return res;
}
@@ -345,6 +359,7 @@
private boolean mMetered;
private boolean mDefaultNetwork;
private int mOemManaged;
+ private int mSubId;
/**
* Creates a new Builder.
@@ -359,6 +374,7 @@
mMetered = false;
mDefaultNetwork = false;
mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
+ mSubId = INVALID_SUBSCRIPTION_ID;
}
/**
@@ -537,6 +553,19 @@
return this;
}
+ /**
+ * Set the Subscription Id.
+ *
+ * @param subId the Subscription Id of the network. Or INVALID_SUBSCRIPTION_ID if not
+ * applicable.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setSubId(int subId) {
+ mSubId = subId;
+ return this;
+ }
+
private void ensureValidParameters() {
// Assert non-mobile network cannot have a ratType.
if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
@@ -559,7 +588,7 @@
public NetworkIdentity build() {
ensureValidParameters();
return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
- mRoaming, mMetered, mDefaultNetwork, mOemManaged);
+ mRoaming, mMetered, mDefaultNetwork, mOemManaged, mSubId);
}
}
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
index dfa347f..56461ba 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
@@ -17,6 +17,7 @@
package android.net;
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.NonNull;
import android.service.NetworkIdentitySetProto;
@@ -42,6 +43,7 @@
private static final int VERSION_ADD_METERED = 4;
private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
+ private static final int VERSION_ADD_SUB_ID = 7;
/**
* Construct a {@link NetworkIdentitySet} object.
@@ -103,8 +105,15 @@
oemNetCapabilities = NetworkIdentity.OEM_NONE;
}
+ final int subId;
+ if (version >= VERSION_ADD_SUB_ID) {
+ subId = in.readInt();
+ } else {
+ subId = INVALID_SUBSCRIPTION_ID;
+ }
+
add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered,
- defaultNetwork, oemNetCapabilities));
+ defaultNetwork, oemNetCapabilities, subId));
}
}
@@ -113,7 +122,7 @@
* @hide
*/
public void writeToStream(DataOutput out) throws IOException {
- out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK);
+ out.writeInt(VERSION_ADD_SUB_ID);
out.writeInt(size());
for (NetworkIdentity ident : this) {
out.writeInt(ident.getType());
@@ -124,6 +133,7 @@
out.writeBoolean(ident.isMetered());
out.writeBoolean(ident.isDefaultNetwork());
out.writeInt(ident.getOemManaged());
+ out.writeInt(ident.getSubId());
}
}
@@ -212,7 +222,7 @@
final long start = proto.start(tag);
for (NetworkIdentity ident : this) {
- ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES);
+ ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES_FIELD_NUMBER);
}
proto.end(start);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl
deleted file mode 100644
index cb602d79..0000000
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * 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.net;
-
-parcelable NetworkStateSnapshot;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
index 3915634..d3f785a 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
@@ -17,6 +17,8 @@
package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -98,12 +100,29 @@
return mLinkProperties;
}
- /** Get the Subscriber Id of the network associated with this snapshot. */
+ /**
+ * Get the Subscriber Id of the network associated with this snapshot.
+ * @deprecated Please use #getSubId, which doesn't return personally identifiable
+ * information.
+ */
+ @Deprecated
@Nullable
public String getSubscriberId() {
return mSubscriberId;
}
+ /** Get the subId of the network associated with this snapshot. */
+ public int getSubId() {
+ if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ final NetworkSpecifier spec = mNetworkCapabilities.getNetworkSpecifier();
+ if (spec instanceof TelephonyNetworkSpecifier) {
+ return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
+ }
+ }
+ return INVALID_SUBSCRIPTION_ID;
+ }
+
+
/**
* Get the legacy type of the network associated with this snapshot.
* @return the legacy network type. See {@code ConnectivityManager#TYPE_*}.
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
index 9175809..f681ba1 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
@@ -28,6 +28,7 @@
import android.os.Parcelable;
import android.os.Process;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -500,7 +501,7 @@
&& roaming == e.roaming && defaultNetwork == e.defaultNetwork
&& rxBytes == e.rxBytes && rxPackets == e.rxPackets
&& txBytes == e.txBytes && txPackets == e.txPackets
- && operations == e.operations && iface.equals(e.iface);
+ && operations == e.operations && TextUtils.equals(iface, e.iface);
}
return false;
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
index 735c44d..67d48f0 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
@@ -732,19 +732,19 @@
final long start = proto.start(tag);
for (Key key : getSortedKeys()) {
- final long startStats = proto.start(NetworkStatsCollectionProto.STATS);
+ final long startStats = proto.start(NetworkStatsCollectionProto.STATS_FIELD_NUMBER);
// Key
- final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY);
- key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY);
- proto.write(NetworkStatsCollectionKeyProto.UID, key.uid);
- proto.write(NetworkStatsCollectionKeyProto.SET, key.set);
- proto.write(NetworkStatsCollectionKeyProto.TAG, key.tag);
+ final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY_FIELD_NUMBER);
+ key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY_FIELD_NUMBER);
+ proto.write(NetworkStatsCollectionKeyProto.UID_FIELD_NUMBER, key.uid);
+ proto.write(NetworkStatsCollectionKeyProto.SET_FIELD_NUMBER, key.set);
+ proto.write(NetworkStatsCollectionKeyProto.TAG_FIELD_NUMBER, key.tag);
proto.end(startKey);
// Value
final NetworkStatsHistory history = mStats.get(key);
- history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY);
+ history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY_FIELD_NUMBER);
proto.end(startStats);
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
index 78c1370..822a16e 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
@@ -915,17 +915,18 @@
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
- proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration);
+ proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS_FIELD_NUMBER, bucketDuration);
for (int i = 0; i < bucketCount; i++) {
- final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS);
+ final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS_FIELD_NUMBER);
- proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS, bucketStart[i]);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i);
- dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i);
+ proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS_FIELD_NUMBER,
+ bucketStart[i]);
+ dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES_FIELD_NUMBER, rxBytes, i);
+ dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS_FIELD_NUMBER, rxPackets, i);
+ dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES_FIELD_NUMBER, txBytes, i);
+ dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS_FIELD_NUMBER, txPackets, i);
+ dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS_FIELD_NUMBER, operations, i);
proto.end(startBucket);
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
index 9b58b01..7b5afd7 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
@@ -79,7 +79,8 @@
MATCH_WIFI,
MATCH_ETHERNET,
MATCH_BLUETOOTH,
- MATCH_CARRIER
+ MATCH_PROXY,
+ MATCH_CARRIER,
})
public @interface TemplateMatchRule{}
@@ -104,9 +105,8 @@
/** Match rule to match bluetooth networks. */
public static final int MATCH_BLUETOOTH = 8;
/**
- * Match rule to match networks with {@link Connectivity#TYPE_PROXY} as the legacy network type.
- *
- * @hide
+ * Match rule to match networks with {@link ConnectivityManager#TYPE_PROXY} as the legacy
+ * network type.
*/
public static final int MATCH_PROXY = 9;
/**
diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
index c2f0cdf..bc836d8 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
@@ -31,12 +31,9 @@
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
+import android.os.StrictMode;
import android.util.Log;
-import com.android.server.NetworkManagementSocketTagger;
-
-import dalvik.system.SocketTagger;
-
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.DatagramSocket;
@@ -56,6 +53,10 @@
* 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.
@@ -232,9 +233,68 @@
*/
@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.
@@ -249,7 +309,7 @@
* @see #clearThreadStatsTag()
*/
public static void setThreadStatsTag(int tag) {
- NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+ getAndSetThreadStatsTag(tag);
}
/**
@@ -267,7 +327,9 @@
* 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;
}
/**
@@ -327,7 +389,7 @@
* @see #setThreadStatsTag(int)
*/
public static int getThreadStatsTag() {
- return NetworkManagementSocketTagger.getThreadSocketStatsTag();
+ return sThreadUidTag.get().tag;
}
/**
@@ -337,7 +399,7 @@
* @see #setThreadStatsTag(int)
*/
public static void clearThreadStatsTag() {
- NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
+ sThreadUidTag.get().tag = -1;
}
/**
@@ -357,7 +419,7 @@
*/
@SuppressLint("RequiresPermission")
public static void setThreadStatsUid(int uid) {
- NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
+ sThreadUidTag.get().uid = uid;
}
/**
@@ -368,7 +430,7 @@
* @see #setThreadStatsUid(int)
*/
public static int getThreadStatsUid() {
- return NetworkManagementSocketTagger.getThreadSocketStatsUid();
+ return sThreadUidTag.get().uid;
}
/**
@@ -395,7 +457,7 @@
*/
@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 0f21e55..512fbce 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.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 @@
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 @@
}
/**
+ * 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 @@
* @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 @@
NsdServiceInfo s = new NsdServiceInfo();
s.setServiceType(serviceType);
+ s.setNetwork(network);
int key = putListener(listener, s);
try {
@@ -679,6 +871,67 @@
}
/**
+ * 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 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 0946499..8506db1 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 @@
private int mPort;
+ @Nullable
+ private Network mNetwork;
+
public NsdServiceInfo() {
}
@@ -307,18 +312,37 @@
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 @@
}
dest.writeString(key);
}
+
+ dest.writeParcelable(mNetwork, 0);
}
/** Implement the Parcelable interface */
@@ -381,6 +407,7 @@
}
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 8bb12a6d..0000000
--- a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
+++ /dev/null
@@ -1,129 +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;
- }
-
- /**
- * 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);
-}
diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp
index 24bc91d..5100e7c 100644
--- a/packages/ConnectivityT/service/Android.bp
+++ b/packages/ConnectivityT/service/Android.bp
@@ -28,6 +28,11 @@
"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: [
@@ -35,6 +40,30 @@
],
}
+// For test code only.
+filegroup {
+ name: "lib_networkStatsFactory_native",
+ srcs: [
+ "jni/com_android_server_net_NetworkStatsFactory.cpp",
+ ],
+ path: "jni",
+ visibility: [
+ "//packages/modules/Connectivity:__subpackages__",
+ ],
+}
+
+filegroup {
+ name: "services.connectivity-netstats-jni-sources",
+ srcs: [
+ "jni/com_android_server_net_NetworkStatsFactory.cpp",
+ "jni/com_android_server_net_NetworkStatsService.cpp",
+ ],
+ path: "jni",
+ visibility: [
+ "//packages/modules/Connectivity:__subpackages__",
+ ],
+}
+
// Nsd related libraries.
filegroup {
@@ -83,8 +112,6 @@
name: "services.connectivity-tiramisu-sources",
srcs: [
":services.connectivity-ethernet-sources",
- ":services.connectivity-ipsec-sources",
- ":services.connectivity-netstats-sources",
],
path: "src",
visibility: ["//frameworks/base/services/core"],
@@ -93,6 +120,8 @@
filegroup {
name: "services.connectivity-tiramisu-updatable-sources",
srcs: [
+ ":services.connectivity-ipsec-sources",
+ ":services.connectivity-netstats-sources",
":services.connectivity-nsd-sources",
],
path: "src",
diff --git a/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp b/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp
similarity index 100%
rename from services/core/jni/com_android_server_net_NetworkStatsFactory.cpp
rename to packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsFactory.cpp
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp
similarity index 94%
rename from services/core/jni/com_android_server_net_NetworkStatsService.cpp
rename to packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp
index f8a8168..39cbaf7 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/packages/ConnectivityT/service/jni/com_android_server_net_NetworkStatsService.cpp
@@ -102,15 +102,10 @@
}
}
-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/packages/ConnectivityT/service/src/com/android/server/IpSecService.java b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
index 179d945..4bc40ea 100644
--- a/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/IpSecService.java
@@ -1008,16 +1008,10 @@
*
* @param context Binder context for this service
*/
- private IpSecService(Context context) {
+ public IpSecService(Context context) {
this(context, new Dependencies());
}
- static IpSecService create(Context context)
- throws InterruptedException {
- final IpSecService service = new IpSecService(context);
- return service;
- }
-
@NonNull
private AppOpsManager getAppOpsManager() {
AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
@@ -1054,26 +1048,6 @@
}
}
- /** Called by system server when system is ready. */
- public void systemReady() {
- if (isNetdAlive()) {
- Log.d(TAG, "IpSecService is ready");
- } else {
- Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!");
- }
- }
-
- synchronized boolean isNetdAlive() {
- try {
- if (mNetd == null) {
- return false;
- }
- return mNetd.isAlive();
- } catch (RemoteException re) {
- return false;
- }
- }
-
/**
* Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be
* a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1.
@@ -1896,7 +1870,6 @@
mContext.enforceCallingOrSelfPermission(DUMP, TAG);
pw.println("IpSecService dump:");
- pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead"));
pw.println();
pw.println("mUserResourceTracker:");
diff --git a/packages/ConnectivityT/service/src/com/android/server/NsdService.java b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
index 497107d..ddf6d2c 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 @@
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 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 @@
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 @@
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 @@
}
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 @@
/* 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 @@
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 @@
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 @@
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 {
- clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
+ 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 {
+ 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 @@
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 @@
}
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 0000000..443e5b3
--- /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 0000000..93b9195
--- /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 061f323..42c0044 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 17f3455..151c90d 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_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;
@@ -56,6 +54,10 @@
* @hide
*/
public class NetworkStatsFactory {
+ static {
+ System.loadLibrary("service-connectivity");
+ }
+
private static final String TAG = "NetworkStatsFactory";
private static final boolean USE_NATIVE_PARSING = true;
@@ -470,6 +472,19 @@
}
/**
+ * 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 1953624..fdfc893 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
@@ -19,8 +19,11 @@
import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES;
import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.DataUsageRequest;
import android.net.NetworkIdentitySet;
+import android.net.NetworkStack;
import android.net.NetworkStats;
import android.net.NetworkStatsAccess;
import android.net.NetworkStatsCollection;
@@ -74,9 +77,9 @@
*
* @return the normalized request wrapped within {@link RequestInfo}.
*/
- public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback,
- int callingUid, @NetworkStatsAccess.Level int accessLevel) {
- DataUsageRequest request = buildRequest(inputRequest, callingUid);
+ public DataUsageRequest register(Context context, DataUsageRequest inputRequest,
+ IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
+ DataUsageRequest request = buildRequest(context, inputRequest, callingUid);
RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
accessLevel);
@@ -194,10 +197,13 @@
}
}
- 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
+ private DataUsageRequest buildRequest(Context context, DataUsageRequest request,
+ int callingUid) {
+ // For non-NETWORK_STACK permission uid, cap the minimum threshold to a safe default to
+ // avoid too many callbacks.
+ final long thresholdInBytes = (context.checkPermission(
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, Process.myPid(), callingUid)
+ == PackageManager.PERMISSION_GRANTED ? request.thresholdInBytes
: Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes));
if (thresholdInBytes > request.thresholdInBytes) {
Log.w(TAG, "Threshold was too low for " + request
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java
index c371f08..a006cd5 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsRecorder.java
@@ -471,9 +471,11 @@
public void dumpDebugLocked(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
if (mPending != null) {
- proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES, mPending.getTotalBytes());
+ proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES_FIELD_NUMBER,
+ mPending.getTotalBytes());
}
- getOrLoadCompleteLocked().dumpDebug(proto, NetworkStatsRecorderProto.COMPLETE_HISTORY);
+ getOrLoadCompleteLocked().dumpDebug(proto,
+ NetworkStatsRecorderProto.COMPLETE_HISTORY_FIELD_NUMBER);
proto.end(start);
}
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 9f3371b..ef6f39a 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -51,6 +51,7 @@
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.system.OsConstants.ENOENT;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
@@ -62,6 +63,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.usage.NetworkStatsManager;
@@ -102,6 +104,7 @@
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
import android.os.Binder;
+import android.os.Build;
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
@@ -120,7 +123,6 @@
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;
@@ -169,7 +171,12 @@
* Collect and persist detailed network statistics, and provide this data to
* other system services.
*/
+@TargetApi(Build.VERSION_CODES.TIRAMISU)
public class NetworkStatsService extends INetworkStatsService.Stub {
+ static {
+ System.loadLibrary("service-connectivity");
+ }
+
static final String TAG = "NetworkStats";
static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
@@ -214,6 +221,14 @@
// 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 static final String COOKIE_TAG_MAP_PATH =
+ "/sys/fs/bpf/map_netd_cookie_tag_map";
+ private static final String APP_UID_STATS_MAP_PATH =
+ "/sys/fs/bpf/map_netd_app_uid_stats_map";
+ private static final String STATS_MAP_A_PATH =
+ "/sys/fs/bpf/map_netd_stats_map_A";
+ private static final String STATS_MAP_B_PATH =
+ "/sys/fs/bpf/map_netd_stats_map_B";
private final Context mContext;
private final NetworkStatsFactory mStatsFactory;
@@ -341,6 +356,10 @@
*/
private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
private final IBpfMap<U32, U8> mUidCounterSetMap;
+ private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap;
+ private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapA;
+ private final IBpfMap<StatsMapKey, StatsMapValue> mStatsMapB;
+ private final IBpfMap<UidStatsMapKey, StatsMapValue> mAppUidStatsMap;
/** Data layer operation counters for splicing into other structures. */
private NetworkStats mUidOperations = new NetworkStats(0L, 10);
@@ -474,6 +493,10 @@
mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler);
mInterfaceMapUpdater.start();
mUidCounterSetMap = mDeps.getUidCounterSetMap();
+ mCookieTagMap = mDeps.getCookieTagMap();
+ mStatsMapA = mDeps.getStatsMapA();
+ mStatsMapB = mDeps.getStatsMapB();
+ mAppUidStatsMap = mDeps.getAppUidStatsMap();
}
/**
@@ -547,8 +570,48 @@
}
}
- public TagStatsDeleter getTagStatsDeleter() {
- return NetworkStatsService::nativeDeleteTagData;
+ /** Gets the cookie tag map */
+ public IBpfMap<CookieTagMapKey, CookieTagMapValue> getCookieTagMap() {
+ try {
+ return new BpfMap<CookieTagMapKey, CookieTagMapValue>(COOKIE_TAG_MAP_PATH,
+ BpfMap.BPF_F_RDWR, CookieTagMapKey.class, CookieTagMapValue.class);
+ } catch (ErrnoException e) {
+ Log.wtf(TAG, "Cannot create cookie tag map: " + e);
+ return null;
+ }
+ }
+
+ /** Gets stats map A */
+ public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapA() {
+ try {
+ return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_A_PATH,
+ BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
+ } catch (ErrnoException e) {
+ Log.wtf(TAG, "Cannot create stats map A: " + e);
+ return null;
+ }
+ }
+
+ /** Gets stats map B */
+ public IBpfMap<StatsMapKey, StatsMapValue> getStatsMapB() {
+ try {
+ return new BpfMap<StatsMapKey, StatsMapValue>(STATS_MAP_B_PATH,
+ BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class);
+ } catch (ErrnoException e) {
+ Log.wtf(TAG, "Cannot create stats map B: " + e);
+ return null;
+ }
+ }
+
+ /** Gets the uid stats map */
+ public IBpfMap<UidStatsMapKey, StatsMapValue> getAppUidStatsMap() {
+ try {
+ return new BpfMap<UidStatsMapKey, StatsMapValue>(APP_UID_STATS_MAP_PATH,
+ BpfMap.BPF_F_RDWR, UidStatsMapKey.class, StatsMapValue.class);
+ } catch (ErrnoException e) {
+ Log.wtf(TAG, "Cannot create app uid stats map: " + e);
+ return null;
+ }
}
}
@@ -1060,7 +1123,7 @@
@Override
public NetworkStats getUidStatsForTransport(int transport) {
- enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
try {
final String[] relevantIfaces =
transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces;
@@ -1222,7 +1285,7 @@
DataUsageRequest normalizedRequest;
final long token = Binder.clearCallingIdentity();
try {
- normalizedRequest = mStatsObservers.register(
+ normalizedRequest = mStatsObservers.register(mContext,
request, callback, callingUid, accessLevel);
} finally {
Binder.restoreCallingIdentity(token);
@@ -1477,10 +1540,15 @@
NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) {
// Copy the identify from IMS one but mark it as metered.
- NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
- ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(),
- ident.isRoaming(), true /* metered */,
- true /* onDefaultNetwork */, ident.getOemManaged());
+ NetworkIdentity vtIdent = new NetworkIdentity.Builder()
+ .setType(ident.getType())
+ .setRatType(ident.getRatType())
+ .setSubscriberId(ident.getSubscriberId())
+ .setWifiNetworkKey(ident.getWifiNetworkKey())
+ .setRoaming(ident.isRoaming()).setMetered(true)
+ .setDefaultNetwork(true)
+ .setOemManaged(ident.getOemManaged())
+ .setSubId(ident.getSubId()).build();
final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent);
@@ -1790,6 +1858,69 @@
currentTime);
}
+ // deleteKernelTagData can ignore ENOENT; otherwise we should log an error
+ private void logErrorIfNotErrNoent(final ErrnoException e, final String msg) {
+ if (e.errno != ENOENT) Log.e(TAG, msg, e);
+ }
+
+ private <K extends StatsMapKey, V extends StatsMapValue> void deleteStatsMapTagData(
+ IBpfMap<K, V> statsMap, int uid) {
+ try {
+ statsMap.forEach((key, value) -> {
+ if (key.uid == uid) {
+ try {
+ statsMap.deleteEntry(key);
+ } catch (ErrnoException e) {
+ logErrorIfNotErrNoent(e, "Failed to delete data(uid = " + key.uid + ")");
+ }
+ }
+ });
+ } catch (ErrnoException e) {
+ Log.e(TAG, "FAILED to delete tag data from stats map", e);
+ }
+ }
+
+ /**
+ * Deletes uid tag data from CookieTagMap, StatsMapA, StatsMapB, and UidStatsMap
+ * @param uid
+ */
+ private void deleteKernelTagData(int uid) {
+ try {
+ mCookieTagMap.forEach((key, value) -> {
+ // If SkDestroyListener deletes the socket tag while this code is running,
+ // forEach will either restart iteration from the beginning or return null,
+ // depending on when the deletion happens.
+ // If it returns null, continue iteration to delete the data and in fact it would
+ // just iterate from first key because BpfMap#getNextKey would return first key
+ // if the current key is not exist.
+ if (value != null && value.uid == uid) {
+ try {
+ mCookieTagMap.deleteEntry(key);
+ } catch (ErrnoException e) {
+ logErrorIfNotErrNoent(e, "Failed to delete data(cookie = " + key + ")");
+ }
+ }
+ });
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Failed to delete tag data from cookie tag map", e);
+ }
+
+ deleteStatsMapTagData(mStatsMapA, uid);
+ deleteStatsMapTagData(mStatsMapB, uid);
+
+ try {
+ mUidCounterSetMap.deleteEntry(new U32(uid));
+ } catch (ErrnoException e) {
+ logErrorIfNotErrNoent(e, "Failed to delete tag data from uid counter set map");
+ }
+
+ try {
+ mAppUidStatsMap.deleteEntry(new UidStatsMapKey(uid));
+ } catch (ErrnoException e) {
+ logErrorIfNotErrNoent(e, "Failed to delete tag data from app uid stats map");
+ }
+ }
+
/**
* Clean up {@link #mUidRecorder} after UID is removed.
*/
@@ -1805,10 +1936,7 @@
// Clear kernel stats associated with UID
for (int uid : uids) {
- final int ret = mDeps.getTagStatsDeleter().deleteTagData(uid);
- if (ret < 0) {
- Log.w(TAG, "problem clearing counters for uid " + uid + ": " + Os.strerror(-ret));
- }
+ deleteKernelTagData(uid);
}
}
@@ -2004,12 +2132,15 @@
// TODO Right now it writes all history. Should it limit to the "since-boot" log?
- dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces);
- dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces);
- mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
- mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
- mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
- mUidTagRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS);
+ dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES_FIELD_NUMBER,
+ mActiveIfaces);
+ dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES_FIELD_NUMBER,
+ mActiveUidIfaces);
+ mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS_FIELD_NUMBER);
+ mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS_FIELD_NUMBER);
+ mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS_FIELD_NUMBER);
+ mUidTagRecorder.dumpDebugLocked(proto,
+ NetworkStatsServiceDumpProto.UID_TAG_STATS_FIELD_NUMBER);
proto.flush();
}
@@ -2019,8 +2150,8 @@
for (int i = 0; i < ifaces.size(); i++) {
final long start = proto.start(tag);
- proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i));
- ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES);
+ proto.write(NetworkInterfaceProto.INTERFACE_FIELD_NUMBER, ifaces.keyAt(i));
+ ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES_FIELD_NUMBER);
proto.end(start);
}
@@ -2387,12 +2518,4 @@
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 5bba0b1..65ccd20 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -23,7 +23,9 @@
import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
import android.annotation.NonNull;
+import android.annotation.TargetApi;
import android.content.Context;
+import android.os.Build;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyDisplayInfo;
@@ -43,6 +45,7 @@
/**
* Helper class that watches for events that are triggered per subscription.
*/
+@TargetApi(Build.VERSION_CODES.TIRAMISU)
public class NetworkStatsSubscriptionsMonitor extends
SubscriptionManager.OnSubscriptionsChangedListener {
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 0000000..ea8d836
--- /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 0000000..48f26ce
--- /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 0000000..2849f94
--- /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/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
index 72230b4..4117d0f 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
@@ -177,7 +177,7 @@
ret = 0;
break;
case SparseChunk.FILL:
- ret = mCur.fill[(4 - ((int) mLeft & 0x3)) & 0x3];
+ ret = Byte.toUnsignedInt(mCur.fill[(4 - ((int) mLeft & 0x3)) & 0x3]);
break;
default:
throw new IOException("Unsupported Chunk:" + mCur.toString());
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 99e3160..df19c67 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 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 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 @@
*/
@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 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 @@
*/
@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 ddee433..233e798 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 @@
}
/**
+ * 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 9dd329e..7e5c124 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -132,17 +132,12 @@
}
public BluetoothDevice getActiveDevice() {
- if (mService == null) {
+ if (mBluetoothAdapter == null) {
return null;
}
- return mService.getActiveDevice();
- }
-
- public boolean isAudioOn() {
- if (mService == null) {
- return false;
- }
- return mService.isAudioOn();
+ final List<BluetoothDevice> activeDevices = mBluetoothAdapter
+ .getActiveDevices(BluetoothProfile.HEADSET);
+ return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
}
public int getAudioState(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index a1fba4a..ff1368a 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 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 209507a..db6d41e 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.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 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/devicestate/OWNERS b/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS
new file mode 100644
index 0000000..98f4123
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS
@@ -0,0 +1,3 @@
+# Default reviewers for this and subdirectories.
+alexflo@google.com
+chrisgollner@google.com
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
index b4c95e6..c7eb682 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
@@ -39,6 +39,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
import java.util.zip.GZIPInputStream;
/**
@@ -54,6 +56,7 @@
private static final String TAG_FILE_NAME = "file-name";
private static final String TAG_FILE_CONTENT = "file-content";
private static final String ATTR_CONTENT_ID = "contentId";
+ private static final String ATTR_LIBRARY_NAME = "lib";
private static final String HTML_HEAD_STRING =
"<html><head>\n"
@@ -67,8 +70,12 @@
+ "</style>\n"
+ "</head>"
+ "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n"
- + "<div class=\"toc\">\n"
- + "<ul>";
+ + "<div class=\"toc\">";
+ private static final String LIBRARY_HEAD_STRING =
+ "<strong>Libraries</strong>\n<ul class=\"libraries\">";
+ private static final String LIBRARY_TAIL_STRING = "</ul>\n<strong>Files</strong>";
+
+ private static final String FILES_HEAD_STRING = "<ul class=\"files\">";
private static final String HTML_MIDDLE_STRING =
"</ul>\n"
@@ -81,12 +88,14 @@
private final List<File> mXmlFiles;
/*
- * A map from a file name to a content id (MD5 sum of file content) for its license.
- * For example, "/system/priv-app/TeleService/TeleService.apk" maps to
+ * A map from a file name to a library name (may be empty) to a content id (MD5 sum of file
+ * content) for its license.
+ * For example, "/system/priv-app/TeleService/TeleService.apk" maps to "service/Telephony" to
* "9645f39e9db895a4aa6e02cb57294595". Here "9645f39e9db895a4aa6e02cb57294595" is a MD5 sum
* of the content of packages/services/Telephony/MODULE_LICENSE_APACHE2.
*/
- private final Map<String, Set<String>> mFileNameToContentIdMap = new HashMap();
+ private final Map<String, Map<String, Set<String>>> mFileNameToLibraryToContentIdMap =
+ new HashMap();
/*
* A map from a content id (MD5 sum of file content) to a license file content.
@@ -98,7 +107,7 @@
static class ContentIdAndFileNames {
final String mContentId;
- final List<String> mFileNameList = new ArrayList();
+ final Map<String, List<String>> mLibraryToFileNameMap = new TreeMap();
ContentIdAndFileNames(String contentId) {
mContentId = contentId;
@@ -120,7 +129,7 @@
parse(xmlFile);
}
- if (mFileNameToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) {
+ if (mFileNameToLibraryToContentIdMap.isEmpty() || mContentIdToFileContentMap.isEmpty()) {
return false;
}
@@ -128,7 +137,7 @@
try {
writer = new PrintWriter(outputFile);
- generateHtml(mFileNameToContentIdMap, mContentIdToFileContentMap, writer,
+ generateHtml(mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap, writer,
noticeHeader);
writer.flush();
@@ -157,7 +166,7 @@
in = new FileReader(xmlFile);
}
- parse(in, mFileNameToContentIdMap, mContentIdToFileContentMap);
+ parse(in, mFileNameToLibraryToContentIdMap, mContentIdToFileContentMap);
in.close();
} catch (XmlPullParserException | IOException e) {
@@ -180,7 +189,8 @@
*
* <licenses>
* <file-name contentId="content_id_of_license1">file1</file-name>
- * <file-name contentId="content_id_of_license2">file2</file-name>
+ * <file-name contentId="content_id_of_license2" lib="name of library">file2</file-name>
+ * <file-name contentId="content_id_of_license2" lib="another library">file2</file-name>
* ...
* <file-content contentId="content_id_of_license1">license1 file contents</file-content>
* <file-content contentId="content_id_of_license2">license2 file contents</file-content>
@@ -188,10 +198,12 @@
* </licenses>
*/
@VisibleForTesting
- static void parse(InputStreamReader in, Map<String, Set<String>> outFileNameToContentIdMap,
+ static void parse(InputStreamReader in,
+ Map<String, Map<String, Set<String>>> outFileNameToLibraryToContentIdMap,
Map<String, String> outContentIdToFileContentMap)
throws XmlPullParserException, IOException {
- Map<String, Set<String>> fileNameToContentIdMap = new HashMap<String, Set<String>>();
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap =
+ new HashMap<String, Map<String, Set<String>>>();
Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
XmlPullParser parser = Xml.newPullParser();
@@ -205,12 +217,15 @@
if (state == XmlPullParser.START_TAG) {
if (TAG_FILE_NAME.equals(parser.getName())) {
String contentId = parser.getAttributeValue("", ATTR_CONTENT_ID);
+ String libraryName = parser.getAttributeValue("", ATTR_LIBRARY_NAME);
if (!TextUtils.isEmpty(contentId)) {
String fileName = readText(parser).trim();
if (!TextUtils.isEmpty(fileName)) {
- Set<String> contentIds =
- fileNameToContentIdMap.computeIfAbsent(
- fileName, k -> new HashSet<>());
+ Map<String, Set<String>> libs =
+ fileNameToLibraryToContentIdMap.computeIfAbsent(
+ fileName, k -> new HashMap<>());
+ Set<String> contentIds = libs.computeIfAbsent(
+ libraryName, k -> new HashSet<>());
contentIds.add(contentId);
}
}
@@ -229,11 +244,17 @@
state = parser.next();
}
- for (Map.Entry<String, Set<String>> entry : fileNameToContentIdMap.entrySet()) {
- outFileNameToContentIdMap.merge(
- entry.getKey(), entry.getValue(), (s1, s2) -> {
- s1.addAll(s2);
- return s1;
+ for (Map.Entry<String, Map<String, Set<String>>> mapEntry :
+ fileNameToLibraryToContentIdMap.entrySet()) {
+ outFileNameToLibraryToContentIdMap.merge(
+ mapEntry.getKey(), mapEntry.getValue(), (m1, m2) -> {
+ for (Map.Entry<String, Set<String>> entry : m2.entrySet()) {
+ m1.merge(entry.getKey(), entry.getValue(), (s1, s2) -> {
+ s1.addAll(s2);
+ return s1;
+ });
+ }
+ return m1;
});
}
outContentIdToFileContentMap.putAll(contentIdToFileContentMap);
@@ -251,13 +272,28 @@
}
@VisibleForTesting
- static void generateHtml(Map<String, Set<String>> fileNameToContentIdMap,
+ static void generateHtml(Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap,
Map<String, String> contentIdToFileContentMap, PrintWriter writer,
String noticeHeader) {
List<String> fileNameList = new ArrayList();
- fileNameList.addAll(fileNameToContentIdMap.keySet());
+ fileNameList.addAll(fileNameToLibraryToContentIdMap.keySet());
Collections.sort(fileNameList);
+ SortedMap<String, Set<String>> libraryToContentIdMap = new TreeMap();
+ for (Map<String, Set<String>> libraryToContentValue :
+ fileNameToLibraryToContentIdMap.values()) {
+ for (Map.Entry<String, Set<String>> entry : libraryToContentValue.entrySet()) {
+ if (TextUtils.isEmpty(entry.getKey())) {
+ continue;
+ }
+ libraryToContentIdMap.merge(
+ entry.getKey(), entry.getValue(), (s1, s2) -> {
+ s1.addAll(s2);
+ return s1;
+ });
+ }
+ }
+
writer.println(HTML_HEAD_STRING);
if (!TextUtils.isEmpty(noticeHeader)) {
@@ -268,21 +304,58 @@
Map<String, Integer> contentIdToOrderMap = new HashMap();
List<ContentIdAndFileNames> contentIdAndFileNamesList = new ArrayList();
+ if (!libraryToContentIdMap.isEmpty()) {
+ writer.println(LIBRARY_HEAD_STRING);
+ for (Map.Entry<String, Set<String>> entry: libraryToContentIdMap.entrySet()) {
+ String libraryName = entry.getKey();
+ for (String contentId : entry.getValue()) {
+ // Assigns an id to a newly referred license file content.
+ if (!contentIdToOrderMap.containsKey(contentId)) {
+ contentIdToOrderMap.put(contentId, count);
+
+ // An index in contentIdAndFileNamesList is the order of each element.
+ contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId));
+ count++;
+ }
+ int id = contentIdToOrderMap.get(contentId);
+ writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, libraryName);
+ }
+ }
+ writer.println(LIBRARY_TAIL_STRING);
+ }
+
+ writer.println(FILES_HEAD_STRING);
+
// Prints all the file list with a link to its license file content.
for (String fileName : fileNameList) {
- for (String contentId : fileNameToContentIdMap.get(fileName)) {
- // Assigns an id to a newly referred license file content.
- if (!contentIdToOrderMap.containsKey(contentId)) {
- contentIdToOrderMap.put(contentId, count);
-
- // An index in contentIdAndFileNamesList is the order of each element.
- contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId));
- count++;
+ for (Map.Entry<String, Set<String>> libToContentId :
+ fileNameToLibraryToContentIdMap.get(fileName).entrySet()) {
+ String libraryName = libToContentId.getKey();
+ if (libraryName == null) {
+ libraryName = "";
}
+ for (String contentId : libToContentId.getValue()) {
+ // Assigns an id to a newly referred license file content.
+ if (!contentIdToOrderMap.containsKey(contentId)) {
+ contentIdToOrderMap.put(contentId, count);
- int id = contentIdToOrderMap.get(contentId);
- contentIdAndFileNamesList.get(id).mFileNameList.add(fileName);
- writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, fileName);
+ // An index in contentIdAndFileNamesList is the order of each element.
+ contentIdAndFileNamesList.add(new ContentIdAndFileNames(contentId));
+ count++;
+ }
+
+ int id = contentIdToOrderMap.get(contentId);
+ ContentIdAndFileNames elem = contentIdAndFileNamesList.get(id);
+ List<String> files = elem.mLibraryToFileNameMap.computeIfAbsent(
+ libraryName, k -> new ArrayList());
+ files.add(fileName);
+ if (TextUtils.isEmpty(libraryName)) {
+ writer.format("<li><a href=\"#id%d\">%s</a></li>\n", id, fileName);
+ } else {
+ writer.format("<li><a href=\"#id%d\">%s - %s</a></li>\n",
+ id, fileName, libraryName);
+ }
+ }
}
}
@@ -292,19 +365,27 @@
// Prints all contents of the license files in order of id.
for (ContentIdAndFileNames contentIdAndFileNames : contentIdAndFileNamesList) {
writer.format("<tr id=\"id%d\"><td class=\"same-license\">\n", count);
- writer.println("<div class=\"label\">Notices for file(s):</div>");
- writer.println("<div class=\"file-list\">");
- for (String fileName : contentIdAndFileNames.mFileNameList) {
- writer.format("%s <br/>\n", fileName);
+ for (Map.Entry<String, List<String>> libraryFiles :
+ contentIdAndFileNames.mLibraryToFileNameMap.entrySet()) {
+ String libraryName = libraryFiles.getKey();
+ if (TextUtils.isEmpty(libraryName)) {
+ writer.println("<div class=\"label\">Notices for file(s):</div>");
+ } else {
+ writer.format("<div class=\"label\"><strong>%s</strong> used by:</div>\n",
+ libraryName);
+ }
+ writer.println("<div class=\"file-list\">");
+ for (String fileName : libraryFiles.getValue()) {
+ writer.format("%s <br/>\n", fileName);
+ }
+ writer.println("</div><!-- file-list -->");
+ count++;
}
- writer.println("</div><!-- file-list -->");
writer.println("<pre class=\"license-text\">");
writer.println(contentIdToFileContentMap.get(
contentIdAndFileNames.mContentId));
writer.println("</pre><!-- license-text -->");
writer.println("</td></tr><!-- same-license -->");
-
- count++;
}
writer.println(HTML_REAR_STRING);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/OWNERS b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/OWNERS
new file mode 100644
index 0000000..98f4123
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/OWNERS
@@ -0,0 +1,3 @@
+# Default reviewers for this and subdirectories.
+alexflo@google.com
+chrisgollner@google.com
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 f167721..bb6b293 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 @@
private BluetoothDevice mDevice;
@Mock
private BluetoothA2dp mBluetoothA2dp;
+ @Mock
+ private BluetoothAdapter mBluetoothAdapter;
private BluetoothProfile.ServiceListener mServiceListener;
private A2dpProfile mProfile;
@@ -72,7 +74,8 @@
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
@@ -203,9 +206,8 @@
when(config.isMandatoryCodec()).thenReturn(false);
when(config.getCodecType()).thenReturn(4);
- when(config.getCodecName()).thenReturn("LDAC");
assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(
- String.format(KNOWN_CODEC_LABEL, config.getCodecName()));
+ String.format(KNOWN_CODEC_LABEL, "LDAC"));
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index d53a3e8..298ee90 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -28,6 +28,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
+import android.os.Parcel;
import android.os.ParcelUuid;
import org.junit.Before;
@@ -60,9 +61,9 @@
private final static Map<Integer, ParcelUuid> CAP_GROUP2 =
Map.of(2, BluetoothUuid.CAP);
private final BluetoothClass DEVICE_CLASS_1 =
- new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+ createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
private final BluetoothClass DEVICE_CLASS_2 =
- new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+ createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
@Mock
private LocalBluetoothProfileManager mLocalProfileManager;
@Mock
@@ -92,6 +93,16 @@
private HearingAidDeviceManager mHearingAidDeviceManager;
private Context mContext;
+ private BluetoothClass createBtClass(int deviceClass) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(deviceClass);
+ p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+ BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+ p.recycle();
+ return bluetoothClass;
+ }
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
index 30182c4..f5ce664 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
@@ -55,15 +55,6 @@
}
@Test
- public void bluetoothProfile_shouldReturnTheAudioStatusFromBlueToothHeadsetService() {
- when(mService.isAudioOn()).thenReturn(true);
- assertThat(mProfile.isAudioOn()).isTrue();
-
- when(mService.isAudioOn()).thenReturn(false);
- assertThat(mProfile.isAudioOn()).isFalse();
- }
-
- @Test
public void testHeadsetProfile_shouldReturnAudioState() {
when(mService.getAudioState(mBluetoothDevice)).
thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index 7be176a..a8e6075 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -28,6 +28,7 @@
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
+import android.os.Parcel;
import org.junit.Before;
import org.junit.Test;
@@ -48,7 +49,7 @@
private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
private final BluetoothClass DEVICE_CLASS =
- new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+ createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
@Mock
private LocalBluetoothProfileManager mLocalProfileManager;
@Mock
@@ -67,6 +68,16 @@
private HearingAidDeviceManager mHearingAidDeviceManager;
private Context mContext;
+ private BluetoothClass createBtClass(int deviceClass) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(deviceClass);
+ p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+ BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+ p.recycle();
+ return bluetoothClass;
+ }
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
index e87461f..09b0d7f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
@@ -36,7 +36,7 @@
@RunWith(RobolectricTestRunner.class)
public class LicenseHtmlGeneratorFromXmlTest {
- private static final String VALILD_XML_STRING =
+ private static final String VALID_OLD_XML_STRING =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<licenses>\n"
+ "<file-name contentId=\"0\">/file0</file-name>\n"
@@ -44,7 +44,15 @@
+ "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n"
+ "</licenses>";
- private static final String INVALILD_XML_STRING =
+ private static final String VALID_NEW_XML_STRING =
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ + "<licenses>\n"
+ + "<file-name contentId=\"0\" lib=\"libA\">/file0</file-name>\n"
+ + "<file-name contentId=\"0\" lib=\"libB\">/file1</file-name>\n"
+ + "<file-content contentId=\"0\"><![CDATA[license content #0]]></file-content>\n"
+ + "</licenses>";
+
+ private static final String INVALID_XML_STRING =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<licenses2>\n"
+ "<file-name contentId=\"0\">/file0</file-name>\n"
@@ -64,13 +72,13 @@
+ "</style>\n"
+ "</head>"
+ "<body topmargin=\"0\" leftmargin=\"0\" rightmargin=\"0\" bottommargin=\"0\">\n"
- + "<div class=\"toc\">\n"
- + "<ul>\n";
+ + "<div class=\"toc\">\n";
private static final String HTML_CUSTOM_HEADING = "Custom heading";
- private static final String HTML_BODY_STRING =
- "<li><a href=\"#id0\">/file0</a></li>\n"
+ private static final String HTML_OLD_BODY_STRING =
+ "<ul class=\"files\">\n"
+ + "<li><a href=\"#id0\">/file0</a></li>\n"
+ "<li><a href=\"#id1\">/file0</a></li>\n"
+ "<li><a href=\"#id0\">/file1</a></li>\n"
+ "</ul>\n"
@@ -97,66 +105,184 @@
+ "</td></tr><!-- same-license -->\n"
+ "</table></body></html>\n";
- private static final String EXPECTED_HTML_STRING = HTML_HEAD_STRING + HTML_BODY_STRING;
+ private static final String HTML_NEW_BODY_STRING =
+ "<strong>Libraries</strong>\n"
+ + "<ul class=\"libraries\">\n"
+ + "<li><a href=\"#id0\">libA</a></li>\n"
+ + "<li><a href=\"#id1\">libB</a></li>\n"
+ + "</ul>\n"
+ + "<strong>Files</strong>\n"
+ + "<ul class=\"files\">\n"
+ + "<li><a href=\"#id0\">/file0 - libA</a></li>\n"
+ + "<li><a href=\"#id1\">/file0 - libB</a></li>\n"
+ + "<li><a href=\"#id0\">/file1 - libA</a></li>\n"
+ + "</ul>\n"
+ + "</div><!-- table of contents -->\n"
+ + "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n"
+ + "<tr id=\"id0\"><td class=\"same-license\">\n"
+ + "<div class=\"label\"><strong>libA</strong> used by:</div>\n"
+ + "<div class=\"file-list\">\n"
+ + "/file0 <br/>\n"
+ + "/file1 <br/>\n"
+ + "</div><!-- file-list -->\n"
+ + "<pre class=\"license-text\">\n"
+ + "license content #0\n"
+ + "</pre><!-- license-text -->\n"
+ + "</td></tr><!-- same-license -->\n"
+ + "<tr id=\"id1\"><td class=\"same-license\">\n"
+ + "<div class=\"label\"><strong>libB</strong> used by:</div>\n"
+ + "<div class=\"file-list\">\n"
+ + "/file0 <br/>\n"
+ + "</div><!-- file-list -->\n"
+ + "<pre class=\"license-text\">\n"
+ + "license content #1\n"
+ + "</pre><!-- license-text -->\n"
+ + "</td></tr><!-- same-license -->\n"
+ + "</table></body></html>\n";
- private static final String EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING =
- HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_BODY_STRING;
+ private static final String EXPECTED_OLD_HTML_STRING = HTML_HEAD_STRING + HTML_OLD_BODY_STRING;
+
+ private static final String EXPECTED_NEW_HTML_STRING = HTML_HEAD_STRING + HTML_NEW_BODY_STRING;
+
+ private static final String EXPECTED_OLD_HTML_STRING_WITH_CUSTOM_HEADING =
+ HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_OLD_BODY_STRING;
+
+ private static final String EXPECTED_NEW_HTML_STRING_WITH_CUSTOM_HEADING =
+ HTML_HEAD_STRING + HTML_CUSTOM_HEADING + "\n" + HTML_NEW_BODY_STRING;
@Test
public void testParseValidXmlStream() throws XmlPullParserException, IOException {
- Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
Map<String, String> contentIdToFileContentMap = new HashMap<>();
LicenseHtmlGeneratorFromXml.parse(
- new InputStreamReader(new ByteArrayInputStream(VALILD_XML_STRING.getBytes())),
- fileNameToContentIdMap, contentIdToFileContentMap);
- assertThat(fileNameToContentIdMap.size()).isEqualTo(2);
- assertThat(fileNameToContentIdMap.get("/file0")).containsExactly("0");
- assertThat(fileNameToContentIdMap.get("/file1")).containsExactly("0");
+ new InputStreamReader(new ByteArrayInputStream(VALID_OLD_XML_STRING.getBytes())),
+ fileNameToLibraryToContentIdMap, contentIdToFileContentMap);
+
+ assertThat(fileNameToLibraryToContentIdMap).hasSize(2);
+ assertThat(fileNameToLibraryToContentIdMap.get("/file0")).hasSize(1);
+ assertThat(fileNameToLibraryToContentIdMap.get("/file1")).hasSize(1);
+ assertThat(fileNameToLibraryToContentIdMap.get("/file0").get(null)).containsExactly("0");
+ assertThat(fileNameToLibraryToContentIdMap.get("/file1").get(null)).containsExactly("0");
+ assertThat(contentIdToFileContentMap.size()).isEqualTo(1);
+ assertThat(contentIdToFileContentMap.get("0")).isEqualTo("license content #0");
+ }
+
+ @Test
+ public void testParseNewValidXmlStream() throws XmlPullParserException, IOException {
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<>();
+
+ LicenseHtmlGeneratorFromXml.parse(
+ new InputStreamReader(new ByteArrayInputStream(VALID_NEW_XML_STRING.getBytes())),
+ fileNameToLibraryToContentIdMap, contentIdToFileContentMap);
+
+ assertThat(fileNameToLibraryToContentIdMap).hasSize(2);
+ assertThat(fileNameToLibraryToContentIdMap.get("/file0")).hasSize(1);
+ assertThat(fileNameToLibraryToContentIdMap.get("/file1")).hasSize(1);
+ assertThat(fileNameToLibraryToContentIdMap.get("/file0").get("libA")).containsExactly("0");
+ assertThat(fileNameToLibraryToContentIdMap.get("/file1").get("libB")).containsExactly("0");
assertThat(contentIdToFileContentMap.size()).isEqualTo(1);
assertThat(contentIdToFileContentMap.get("0")).isEqualTo("license content #0");
}
@Test(expected = XmlPullParserException.class)
public void testParseInvalidXmlStream() throws XmlPullParserException, IOException {
- Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
Map<String, String> contentIdToFileContentMap = new HashMap<>();
LicenseHtmlGeneratorFromXml.parse(
- new InputStreamReader(new ByteArrayInputStream(INVALILD_XML_STRING.getBytes())),
- fileNameToContentIdMap, contentIdToFileContentMap);
+ new InputStreamReader(new ByteArrayInputStream(INVALID_XML_STRING.getBytes())),
+ fileNameToLibraryToContentIdMap, contentIdToFileContentMap);
}
@Test
public void testGenerateHtml() {
- Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
Map<String, String> contentIdToFileContentMap = new HashMap<>();
+ Map<String, Set<String>> toBoth = new HashMap<>();
+ Map<String, Set<String>> toOne = new HashMap<>();
- fileNameToContentIdMap.put("/file0", new HashSet<String>(Arrays.asList("0", "1")));
- fileNameToContentIdMap.put("/file1", new HashSet<String>(Arrays.asList("0")));
+ toBoth.put("", new HashSet<String>(Arrays.asList("0", "1")));
+ toOne.put("", new HashSet<String>(Arrays.asList("0")));
+
+ fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+ fileNameToLibraryToContentIdMap.put("/file1", toOne);
contentIdToFileContentMap.put("0", "license content #0");
contentIdToFileContentMap.put("1", "license content #1");
StringWriter output = new StringWriter();
LicenseHtmlGeneratorFromXml.generateHtml(
- fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output), "");
- assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING);
+ fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+ new PrintWriter(output), "");
+ assertThat(output.toString()).isEqualTo(EXPECTED_OLD_HTML_STRING);
+ }
+
+ @Test
+ public void testGenerateNewHtml() {
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<>();
+ Map<String, Set<String>> toBoth = new HashMap<>();
+ Map<String, Set<String>> toOne = new HashMap<>();
+
+ toBoth.put("libA", new HashSet<String>(Arrays.asList("0")));
+ toBoth.put("libB", new HashSet<String>(Arrays.asList("1")));
+ toOne.put("libA", new HashSet<String>(Arrays.asList("0")));
+
+ fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+ fileNameToLibraryToContentIdMap.put("/file1", toOne);
+ contentIdToFileContentMap.put("0", "license content #0");
+ contentIdToFileContentMap.put("1", "license content #1");
+
+ StringWriter output = new StringWriter();
+ LicenseHtmlGeneratorFromXml.generateHtml(
+ fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+ new PrintWriter(output), "");
+ assertThat(output.toString()).isEqualTo(EXPECTED_NEW_HTML_STRING);
}
@Test
public void testGenerateHtmlWithCustomHeading() {
- Map<String, Set<String>> fileNameToContentIdMap = new HashMap<>();
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
Map<String, String> contentIdToFileContentMap = new HashMap<>();
+ Map<String, Set<String>> toBoth = new HashMap<>();
+ Map<String, Set<String>> toOne = new HashMap<>();
- fileNameToContentIdMap.put("/file0", new HashSet<String>(Arrays.asList("0", "1")));
- fileNameToContentIdMap.put("/file1", new HashSet<String>(Arrays.asList("0")));
+ toBoth.put("", new HashSet<String>(Arrays.asList("0", "1")));
+ toOne.put("", new HashSet<String>(Arrays.asList("0")));
+
+ fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+ fileNameToLibraryToContentIdMap.put("/file1", toOne);
contentIdToFileContentMap.put("0", "license content #0");
contentIdToFileContentMap.put("1", "license content #1");
StringWriter output = new StringWriter();
LicenseHtmlGeneratorFromXml.generateHtml(
- fileNameToContentIdMap, contentIdToFileContentMap, new PrintWriter(output),
- HTML_CUSTOM_HEADING);
- assertThat(output.toString()).isEqualTo(EXPECTED_HTML_STRING_WITH_CUSTOM_HEADING);
+ fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+ new PrintWriter(output), HTML_CUSTOM_HEADING);
+ assertThat(output.toString()).isEqualTo(EXPECTED_OLD_HTML_STRING_WITH_CUSTOM_HEADING);
+ }
+
+ @Test
+ public void testGenerateNewHtmlWithCustomHeading() {
+ Map<String, Map<String, Set<String>>> fileNameToLibraryToContentIdMap = new HashMap<>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<>();
+ Map<String, Set<String>> toBoth = new HashMap<>();
+ Map<String, Set<String>> toOne = new HashMap<>();
+
+ toBoth.put("libA", new HashSet<String>(Arrays.asList("0")));
+ toBoth.put("libB", new HashSet<String>(Arrays.asList("1")));
+ toOne.put("libA", new HashSet<String>(Arrays.asList("0")));
+
+ fileNameToLibraryToContentIdMap.put("/file0", toBoth);
+ fileNameToLibraryToContentIdMap.put("/file1", toOne);
+ contentIdToFileContentMap.put("0", "license content #0");
+ contentIdToFileContentMap.put("1", "license content #1");
+
+ StringWriter output = new StringWriter();
+ LicenseHtmlGeneratorFromXml.generateHtml(
+ fileNameToLibraryToContentIdMap, contentIdToFileContentMap,
+ new PrintWriter(output), HTML_CUSTOM_HEADING);
+ assertThat(output.toString()).isEqualTo(EXPECTED_NEW_HTML_STRING_WITH_CUSTOM_HEADING);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
index 6f7f73a..c122a37 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/MediaDeviceTest.java
@@ -31,6 +31,7 @@
import android.content.Context;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
+import android.os.Parcel;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -65,9 +66,9 @@
private static final String ROUTER_ID_3 = "RouterId_3";
private static final String TEST_PACKAGE_NAME = "com.test.playmusic";
private final BluetoothClass mHeadreeClass =
- new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+ createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
private final BluetoothClass mCarkitClass =
- new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
+ createBtClass(BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO);
@Mock
private BluetoothDevice mDevice1;
@@ -118,6 +119,16 @@
private List<MediaDevice> mMediaDevices = new ArrayList<>();
private PhoneMediaDevice mPhoneMediaDevice;
+ private BluetoothClass createBtClass(int deviceClass) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(deviceClass);
+ p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+ BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+ p.recycle();
+ return bluetoothClass;
+ }
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
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 b0a647e..95f7ef4 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 @@
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 @@
.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 @@
.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/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
index 3b7fbc7..c7e96bc 100644
--- a/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
+++ b/packages/SettingsLib/tests/robotests/testutils/com/android/settingslib/testutils/shadow/ShadowBluetoothAdapter.java
@@ -69,7 +69,7 @@
}
@Implementation
- protected boolean removeActiveDevice(@BluetoothAdapter.ActiveDeviceUse int profiles) {
+ protected boolean removeActiveDevice(int profiles) {
if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
&& profiles != ACTIVE_DEVICE_ALL) {
return false;
@@ -78,8 +78,7 @@
}
@Implementation
- protected boolean setActiveDevice(BluetoothDevice device,
- @BluetoothAdapter.ActiveDeviceUse int profiles) {
+ protected boolean setActiveDevice(BluetoothDevice device, int profiles) {
if (device == null) {
return false;
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5b2e8ae..ca4dcbb 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,7 +507,11 @@
<!-- 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 needed for CTS test - ConcurrencyTest#testP2pExternalApprover
+ P2P external approver API sets require MANAGE_WIFI_AUTO_JOIN permission. -->
+ <uses-permission android:name="android.permission.MANAGE_WIFI_AUTO_JOIN" />
<!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
<uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" />
@@ -532,6 +539,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" />
@@ -551,6 +559,9 @@
<uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
+ <!-- Permission required for CTS test - MediaCodecResourceTest -->
+ <uses-permission android:name="android.permission.MEDIA_RESOURCE_OVERRIDE_PID" />
+
<!-- Permission required for CTS test - ResourceObserverNativeTest -->
<uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
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 d3d6e03..6f30ac3 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 8a47a36..4758ab0 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 @@
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 @@
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 @@
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 @@
)
} ?: 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 @@
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 @@
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
addView(taskView)
+ setAlpha(0f)
}
requireViewById<ImageView>(R.id.control_detail_close).apply {
@@ -134,7 +138,7 @@
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 c50365f..71c5fad 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 @@
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 @@
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 b0071d9..dae375a 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 @@
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 @@
}
}
- mDialog = SensorUseDialog(this, sensor, this)
+ mDialog = SensorUseDialog(this, sensor, this, this)
mDialog!!.show()
}
@@ -212,4 +212,8 @@
.suppressSensorPrivacyReminders(sensor, suppressed)
}
}
+
+ override fun onDismiss(dialog: DialogInterface?) {
+ finish()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index e58ea7b..eddc347 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -234,7 +234,7 @@
ApplicationInfo appInfo =
pm.getApplicationInfo(
pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES, info.userId);
- if (appInfo.isInstantApp()) {
+ if (appInfo != null && appInfo.isInstantApp()) {
postInstantAppNotif(
pkg,
info.userId,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index cd6a778..70e4fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -33,7 +33,6 @@
import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.IVolumeController;
-import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.media.VolumePolicy;
@@ -462,11 +461,15 @@
private boolean checkRoutedToBluetoothW(int stream) {
boolean changed = false;
if (stream == AudioManager.STREAM_MUSIC) {
+ // Note: Here we didn't use DEVICE_OUT_BLE_SPEAKER and DEVICE_OUT_BLE_BROADCAST
+ // Since their values overlap with DEVICE_OUT_EARPIECE and DEVICE_OUT_SPEAKER.
+ // Anyway, we can check BLE devices by using just DEVICE_OUT_BLE_HEADSET.
final boolean routedToBluetooth =
(mAudio.getDevicesForStream(AudioManager.STREAM_MUSIC) &
(AudioManager.DEVICE_OUT_BLUETOOTH_A2DP |
AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
- AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0;
+ AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER |
+ AudioManager.DEVICE_OUT_BLE_HEADSET)) != 0;
changed |= updateStreamRoutedToBluetoothW(stream, routedToBluetooth);
}
return changed;
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 0000000..87b9172
--- /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/Android.bp b/services/Android.bp
index 8947393..e730321 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -42,7 +42,9 @@
SYSTEM_OPTIMIZE_JAVA: {
optimize: {
enabled: true,
- optimize: true,
+ // TODO(b/210510433): Enable optimizations after improving
+ // retracing infra.
+ optimize: false,
shrink: true,
proguard_flags_files: ["proguard.flags"],
},
@@ -176,10 +178,6 @@
name: "libandroid_servers",
defaults: ["libservices.core-libs"],
whole_static_libs: ["libservices.core"],
- required: [
- // TODO: remove after NetworkStatsService is moved to the mainline module.
- "libcom_android_net_module_util_jni",
- ],
}
platform_compat_config {
diff --git a/services/autofill/OWNERS b/services/autofill/OWNERS
index c52751d..edfb211 100644
--- a/services/autofill/OWNERS
+++ b/services/autofill/OWNERS
@@ -1 +1 @@
-include /core/java/android/service/autofill/OWNERS
+include /core/java/android/view/autofill/OWNERS
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 30de4b4..f6d05fa 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -1569,7 +1569,7 @@
}
@Override
- public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {
+ public void onDeviceDisconnected(BluetoothDevice device, int reason) {
Slog.d(LOG_TAG, device.getAddress() + " disconnected w/ reason: (" + reason + ") "
+ BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason));
CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress());
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index 48f5b51..26d76a84 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -51,15 +51,12 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.regex.Matcher;
@@ -128,11 +125,9 @@
// Location of ftrace pipe for notifications from kernel memory tools like KFENCE and KASAN.
private static final String ERROR_REPORT_TRACE_PIPE =
"/sys/kernel/tracing/instances/bootreceiver/trace_pipe";
- // Stop after sending this many reports. See http://b/182159975.
+ // Stop after sending too many reports. See http://b/182159975.
private static final int MAX_ERROR_REPORTS = 8;
private static int sSentReports = 0;
- // Avoid reporing the same bug from processDmesg() twice.
- private static String sLastReportedBug = null;
@Override
public void onReceive(final Context context, Intent intent) {
@@ -175,7 +170,8 @@
* We read from /sys/kernel/tracing/instances/bootreceiver/trace_pipe (set up by the
* system), which will print an ftrace event when a memory corruption is detected in the
* kernel.
- * When an error is detected, we run the dmesg shell command and process its output.
+ * When an error is detected, we set the dmesg.start system property to notify dmesgd
+ * about a new error.
*/
OnFileDescriptorEventListener traceCallback = new OnFileDescriptorEventListener() {
final int mBufferSize = 1024;
@@ -191,8 +187,7 @@
* line, but to be on the safe side we keep reading until the buffer
* contains a '\n' character. In the unlikely case of a very buggy kernel
* the buffer may contain multiple tracing events that cannot be attributed
- * to particular error reports. In that case the latest error report
- * residing in dmesg is picked.
+ * to particular error reports. dmesgd will take care of all errors.
*/
try {
int nbytes = Os.read(fd, mTraceBuffer, 0, mBufferSize);
@@ -201,10 +196,13 @@
if (readStr.indexOf("\n") == -1) {
return OnFileDescriptorEventListener.EVENT_INPUT;
}
- processDmesg(context);
+ if (sSentReports < MAX_ERROR_REPORTS) {
+ SystemProperties.set("dmesgd.start", "1");
+ sSentReports++;
+ }
}
} catch (Exception e) {
- Slog.wtf(TAG, "Error processing dmesg output", e);
+ Slog.wtf(TAG, "Error watching for trace events", e);
return 0; // Unregister the handler.
}
return OnFileDescriptorEventListener.EVENT_INPUT;
@@ -216,157 +214,6 @@
}
- /**
- * Check whether it is safe to collect this dmesg line or not.
- *
- * We only consider lines belonging to KASAN or KFENCE reports, but those may still contain
- * user information, namely the process name:
- *
- * [ 69.547684] [ T6006]c7 6006 CPU: 7 PID: 6006 Comm: sh Tainted: G S C O ...
- *
- * hardware information:
- *
- * [ 69.558923] [ T6006]c7 6006 Hardware name: <REDACTED>
- *
- * or register dump (in KASAN reports only):
- *
- * ... RIP: 0033:0x7f96443109da
- * ... RSP: 002b:00007ffcf0b51b08 EFLAGS: 00000202 ORIG_RAX: 00000000000000af
- * ... RAX: ffffffffffffffda RBX: 000055dc3ee521a0 RCX: 00007f96443109da
- *
- * (on x86_64)
- *
- * ... pc : lpm_cpuidle_enter+0x258/0x384
- * ... lr : lpm_cpuidle_enter+0x1d4/0x384
- * ... sp : ffffff800820bea0
- * ... x29: ffffff800820bea0 x28: ffffffc2305f3ce0
- * ... ...
- * ... x9 : 0000000000000001 x8 : 0000000000000000
- * (on ARM64)
- *
- * We therefore omit the lines that contain "Comm:", "Hardware name:", or match the general
- * purpose register regexp.
- *
- * @param line single line of `dmesg` output.
- * @return updated line with sensitive data removed, or null if the line must be skipped.
- */
- public static String stripSensitiveData(String line) {
- /*
- * General purpose register names begin with "R" on x86_64 and "x" on ARM64. The letter is
- * followed by two symbols (numbers, letters or spaces) and a colon, which is followed by a
- * 16-digit hex number. The optional "_" prefix accounts for ORIG_RAX on x86.
- */
- final String registerRegex = "[ _][Rx]..: [0-9a-f]{16}";
- final Pattern registerPattern = Pattern.compile(registerRegex);
-
- final String corruptionRegex = "Detected corrupted memory at 0x[0-9a-f]+";
- final Pattern corruptionPattern = Pattern.compile(corruptionRegex);
-
- if (line.contains("Comm: ") || line.contains("Hardware name: ")) return null;
- if (registerPattern.matcher(line).find()) return null;
-
- Matcher cm = corruptionPattern.matcher(line);
- if (cm.find()) return cm.group(0);
- return line;
- }
-
- /*
- * Search dmesg output for the last error report from KFENCE or KASAN and copy it to Dropbox.
- *
- * Example report printed by the kernel (redacted to fit into 100 column limit):
- * [ 69.236673] [ T6006]c7 6006 =========================================================
- * [ 69.245688] [ T6006]c7 6006 BUG: KFENCE: out-of-bounds in kfence_handle_page_fault
- * [ 69.245688] [ T6006]c7 6006
- * [ 69.257816] [ T6006]c7 6006 Out-of-bounds access at 0xffffffca75c45000 (...)
- * [ 69.267102] [ T6006]c7 6006 kfence_handle_page_fault+0x1bc/0x208
- * [ 69.273536] [ T6006]c7 6006 __do_kernel_fault+0xa8/0x11c
- * ...
- * [ 69.355427] [ T6006]c7 6006 kfence-#2 [0xffffffca75c46f30-0xffffffca75c46fff, ...
- * [ 69.366938] [ T6006]c7 6006 __d_alloc+0x3c/0x1b4
- * [ 69.371946] [ T6006]c7 6006 d_alloc_parallel+0x48/0x538
- * [ 69.377578] [ T6006]c7 6006 __lookup_slow+0x60/0x15c
- * ...
- * [ 69.547684] [ T6006]c7 6006 CPU: 7 PID: 6006 Comm: sh Tainted: G S C O ...
- * [ 69.558923] [ T6006]c7 6006 Hardware name: <REDACTED>
- * [ 69.567059] [ T6006]c7 6006 =========================================================
- *
- * We rely on the kernel printing task/CPU ID for every log line (CONFIG_PRINTK_CALLER=y).
- * E.g. for the above report the task ID is T6006. Report lines may interleave with lines
- * printed by other kernel tasks, which will have different task IDs, so in order to collect
- * the report we:
- * - find the next occurrence of the "BUG: " line in the kernel log, parse it to obtain the
- * task ID and the tool name;
- * - scan the rest of dmesg output and pick every line that has the same task ID, until we
- * encounter a horizontal ruler, i.e.:
- * [ 69.567059] [ T6006]c7 6006 ======================================================
- * - add that line to the error report, unless it contains sensitive information (see
- * logLinePotentiallySensitive())
- * - repeat the above steps till the last report is found.
- */
- private void processDmesg(Context ctx) throws IOException {
- if (sSentReports == MAX_ERROR_REPORTS) return;
- /*
- * Only SYSTEM_KASAN_ERROR_REPORT and SYSTEM_KFENCE_ERROR_REPORT are supported at the
- * moment.
- */
- final String[] bugTypes = new String[] { "KASAN", "KFENCE" };
- final String tsRegex = "^\\[[^]]+\\] ";
- final String bugRegex =
- tsRegex + "\\[([^]]+)\\].*BUG: (" + String.join("|", bugTypes) + "):";
- final Pattern bugPattern = Pattern.compile(bugRegex);
-
- Process p = new ProcessBuilder("/system/bin/timeout", "-k", "90s", "60s",
- "dmesg").redirectErrorStream(true).start();
- BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line = null;
- String task = null;
- String tool = null;
- String bugTitle = null;
- Pattern reportPattern = null;
- ArrayList<String> currentReport = null;
- String lastReport = null;
-
- while ((line = reader.readLine()) != null) {
- if (currentReport == null) {
- Matcher bm = bugPattern.matcher(line);
- if (!bm.find()) continue;
- task = bm.group(1);
- tool = bm.group(2);
- bugTitle = line;
- currentReport = new ArrayList<String>();
- currentReport.add(line);
- String reportRegex = tsRegex + "\\[" + task + "\\].*";
- reportPattern = Pattern.compile(reportRegex);
- continue;
- }
- Matcher rm = reportPattern.matcher(line);
- if (!rm.matches()) continue;
- if ((line = stripSensitiveData(line)) == null) continue;
- if (line.contains("================================")) {
- lastReport = String.join("\n", currentReport);
- currentReport = null;
- continue;
- }
- currentReport.add(line);
- }
- if (lastReport == null) {
- Slog.w(TAG, "Could not find report in dmesg.");
- return;
- }
-
- // Avoid sending the same bug report twice.
- if (bugTitle.equals(sLastReportedBug)) return;
-
- final String reportTag = "SYSTEM_" + tool + "_ERROR_REPORT";
- final DropBoxManager db = ctx.getSystemService(DropBoxManager.class);
- final String headers = getCurrentBootHeaders();
- final String reportText = headers + lastReport;
-
- addTextToDropBox(db, reportTag, reportText, "/dev/kmsg", LOG_SIZE);
- sLastReportedBug = bugTitle;
- sSentReports++;
- }
-
private void removeOldUpdatePackages(Context context) {
Downloads.removeAllDownloadsByPackage(context, OLD_UPDATER_PACKAGE, OLD_UPDATER_CLASS);
}
@@ -484,7 +331,9 @@
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 +375,10 @@
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 +391,19 @@
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/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 8ea3dd6..1095ba3 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -125,6 +125,8 @@
DiskStatsFreeSpaceProto.FOLDER_CACHE);
reportFreeSpace(new File("/system"), "System", pw, proto,
DiskStatsFreeSpaceProto.FOLDER_SYSTEM);
+ reportFreeSpace(Environment.getMetadataDirectory(), "Metadata", pw, proto,
+ DiskStatsFreeSpaceProto.FOLDER_METADATA);
boolean fileBased = StorageManager.isFileEncryptedNativeOnly();
boolean blockBased = fileBased ? false : StorageManager.isBlockEncrypted();
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index e29e894..e924012 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 @@
}
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 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean startInstallation(String dsuSlot) throws RemoteException {
IGsiService service = getGsiService();
mGsiService = service;
@@ -124,6 +118,7 @@
}
@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 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean closePartition() throws RemoteException {
IGsiService service = getGsiService();
if (service.closePartition() != 0) {
@@ -145,6 +141,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean finishInstallation() throws RemoteException {
IGsiService service = getGsiService();
if (service.closeInstall() != 0) {
@@ -155,21 +152,25 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@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 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean submitFromAshmem(long size) {
try {
return getGsiService().commitGsiChunkFromAshmem(size);
@@ -238,6 +244,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean getAvbPublicKey(AvbPublicKey dst) {
try {
return getGsiService().getAvbPublicKey(dst) == 0;
@@ -247,6 +254,7 @@
}
@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 39ac5ef..b59cd4c 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -21,6 +21,7 @@
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.SHUTDOWN;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
@@ -30,6 +31,7 @@
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
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;
@@ -206,6 +208,11 @@
*/
@GuardedBy("mRulesLock")
private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
+ /**
+ * Contains the per-UID firewall rules that are used when Low Power Standby is enabled.
+ */
+ @GuardedBy("mRulesLock")
+ private SparseIntArray mUidFirewallLowPowerStandbyRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mRulesLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -506,12 +513,14 @@
syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted ");
+ syncFirewallChainLocked(FIREWALL_CHAIN_LOW_POWER_STANDBY, "low power standby ");
final int[] chains = {
FIREWALL_CHAIN_STANDBY,
FIREWALL_CHAIN_DOZABLE,
FIREWALL_CHAIN_POWERSAVE,
- FIREWALL_CHAIN_RESTRICTED
+ FIREWALL_CHAIN_RESTRICTED,
+ FIREWALL_CHAIN_LOW_POWER_STANDBY
};
for (int chain : chains) {
@@ -1438,6 +1447,8 @@
return FIREWALL_CHAIN_NAME_POWERSAVE;
case FIREWALL_CHAIN_RESTRICTED:
return FIREWALL_CHAIN_NAME_RESTRICTED;
+ case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+ return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
default:
throw new IllegalArgumentException("Bad child chain: " + chain);
}
@@ -1453,6 +1464,8 @@
return FIREWALL_ALLOWLIST;
case FIREWALL_CHAIN_RESTRICTED:
return FIREWALL_ALLOWLIST;
+ case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+ return FIREWALL_ALLOWLIST;
default:
return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST;
}
@@ -1571,6 +1584,8 @@
return mUidFirewallPowerSaveRules;
case FIREWALL_CHAIN_RESTRICTED:
return mUidFirewallRestrictedRules;
+ case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+ return mUidFirewallLowPowerStandbyRules;
case FIREWALL_CHAIN_NONE:
return mUidFirewallRules;
default:
@@ -1626,6 +1641,11 @@
pw.println(getFirewallChainState(FIREWALL_CHAIN_RESTRICTED));
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_RESTRICTED,
mUidFirewallRestrictedRules);
+
+ pw.print("UID firewall low power standby chain enabled: ");
+ pw.println(getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY));
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY,
+ mUidFirewallLowPowerStandbyRules);
}
pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
@@ -1749,6 +1769,11 @@
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of restricted mode");
return true;
}
+ if (getFirewallChainState(FIREWALL_CHAIN_LOW_POWER_STANDBY)
+ && mUidFirewallLowPowerStandbyRules.get(uid) != FIREWALL_RULE_ALLOW) {
+ if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of low power standby");
+ return true;
+ }
if (mUidRejectOnMetered.get(uid)) {
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
+ " in the background");
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index ff2308c..1e534b7 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.timedetector.NetworkTimeSuggestion;
@@ -35,11 +36,15 @@
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.TimestampedValue;
import android.provider.Settings;
+import android.util.LocalLog;
import android.util.Log;
import android.util.NtpTrustedTime;
+import android.util.NtpTrustedTime.TimeResult;
import android.util.TimeUtils;
import com.android.internal.util.DumpUtils;
@@ -95,6 +100,13 @@
// connection to happen.
private int mTryAgainCounter;
+ /**
+ * A log that records the decisions to fetch a network time update.
+ * This is logged in bug reports to assist with debugging issues with network time suggestions.
+ */
+ @NonNull
+ private final LocalLog mLocalLog = new LocalLog(30, false /* useLocalTimestamps */);
+
public NetworkTimeUpdateService(Context context) {
mContext = context;
mTime = NtpTrustedTime.getInstance(context);
@@ -143,6 +155,42 @@
}, new IntentFilter(ACTION_POLL));
}
+ /**
+ * Clears the cached NTP time. For use during tests to simulate when no NTP time is available.
+ *
+ * <p>This operation takes place in the calling thread rather than the service's handler thread.
+ */
+ void clearTimeForTests() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.SET_TIME, "clear latest network time");
+
+ mTime.clearCachedTimeResult();
+
+ mLocalLog.log("clearTimeForTests");
+ }
+
+ /**
+ * Forces the service to refresh the NTP time.
+ *
+ * <p>This operation takes place in the calling thread rather than the service's handler thread.
+ * This method does not affect currently scheduled refreshes. If the NTP request is successful
+ * it will make an (asynchronously handled) suggestion to the time detector.
+ */
+ boolean forceRefreshForTests() {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.SET_TIME, "force network time refresh");
+
+ boolean success = mTime.forceRefresh();
+ mLocalLog.log("forceRefreshForTests: success=" + success);
+
+ if (success) {
+ makeNetworkTimeSuggestion(mTime.getCachedTimeResult(),
+ "Origin: NetworkTimeUpdateService: forceRefreshForTests");
+ }
+
+ return success;
+ }
+
private void onPollNetworkTime(int event) {
// If we don't have any default network, don't bother.
if (mDefaultNetwork == null) return;
@@ -155,24 +203,37 @@
}
private void onPollNetworkTimeUnderWakeLock(int event) {
+ long currentElapsedRealtimeMillis = SystemClock.elapsedRealtime();
// Force an NTP fix when outdated
NtpTrustedTime.TimeResult cachedNtpResult = mTime.getCachedTimeResult();
- if (cachedNtpResult == null || cachedNtpResult.getAgeMillis() >= mPollingIntervalMs) {
+ if (cachedNtpResult == null || cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis)
+ >= mPollingIntervalMs) {
if (DBG) Log.d(TAG, "Stale NTP fix; forcing refresh");
- mTime.forceRefresh();
+ boolean isSuccessful = mTime.forceRefresh();
+ if (isSuccessful) {
+ mTryAgainCounter = 0;
+ } else {
+ String logMsg = "forceRefresh() returned false: cachedNtpResult=" + cachedNtpResult
+ + ", currentElapsedRealtimeMillis=" + currentElapsedRealtimeMillis;
+
+ if (DBG) {
+ Log.d(TAG, logMsg);
+ }
+ mLocalLog.log(logMsg);
+ }
+
cachedNtpResult = mTime.getCachedTimeResult();
}
- if (cachedNtpResult != null && cachedNtpResult.getAgeMillis() < mPollingIntervalMs) {
+ if (cachedNtpResult != null
+ && cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis)
+ < mPollingIntervalMs) {
// Obtained fresh fix; schedule next normal update
- resetAlarm(mPollingIntervalMs);
+ resetAlarm(mPollingIntervalMs
+ - cachedNtpResult.getAgeMillis(currentElapsedRealtimeMillis));
- // Suggest the time to the time detector. It may choose use it to set the system clock.
- TimestampedValue<Long> timeSignal = new TimestampedValue<>(
- cachedNtpResult.getElapsedRealtimeMillis(), cachedNtpResult.getTimeMillis());
- NetworkTimeSuggestion timeSuggestion = new NetworkTimeSuggestion(timeSignal);
- timeSuggestion.addDebugInfo("Origin: NetworkTimeUpdateService. event=" + event);
- mTimeDetector.suggestNetworkTime(timeSuggestion);
+ makeNetworkTimeSuggestion(cachedNtpResult,
+ "Origin: NetworkTimeUpdateService. event=" + event);
} else {
// No fresh fix; schedule retry
mTryAgainCounter++;
@@ -180,12 +241,26 @@
resetAlarm(mPollingIntervalShorterMs);
} else {
// Try much later
+ String logMsg = "mTryAgainTimesMax exceeded, cachedNtpResult=" + cachedNtpResult;
+ if (DBG) {
+ Log.d(TAG, logMsg);
+ }
+ mLocalLog.log(logMsg);
mTryAgainCounter = 0;
resetAlarm(mPollingIntervalMs);
}
}
}
+ /** Suggests the time to the time detector. It may choose use it to set the system clock. */
+ private void makeNetworkTimeSuggestion(TimeResult ntpResult, String debugInfo) {
+ TimestampedValue<Long> timeSignal = new TimestampedValue<>(
+ ntpResult.getElapsedRealtimeMillis(), ntpResult.getTimeMillis());
+ NetworkTimeSuggestion timeSuggestion = new NetworkTimeSuggestion(timeSignal);
+ timeSuggestion.addDebugInfo(debugInfo);
+ mTimeDetector.suggestNetworkTime(timeSuggestion);
+ }
+
/**
* Cancel old alarm and starts a new one for the specified interval.
*
@@ -285,6 +360,15 @@
if (ntpResult != null) {
pw.println("NTP result age: " + ntpResult.getAgeMillis());
}
+ pw.println("Local logs:");
+ mLocalLog.dump(fd, pw, args);
pw.println();
}
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ new NetworkTimeUpdateServiceShellCommand(this).exec(
+ this, in, out, err, args, callback, resultReceiver);
+ }
}
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
new file mode 100644
index 0000000..dc93023
--- /dev/null
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
@@ -0,0 +1,90 @@
+/*
+ * 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;
+
+import android.annotation.NonNull;
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+import java.util.Objects;
+
+/** Implements the shell command interface for {@link NetworkTimeUpdateService}. */
+class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
+
+ /**
+ * The name of the service.
+ */
+ private static final String SHELL_COMMAND_SERVICE_NAME = "network_time_update_service";
+
+ /**
+ * A shell command that clears the time signal received from the network.
+ */
+ private static final String SHELL_COMMAND_CLEAR_TIME = "clear_time";
+
+ /**
+ * A shell command that forces the time signal to be refreshed from the network.
+ */
+ private static final String SHELL_COMMAND_FORCE_REFRESH = "force_refresh";
+
+ @NonNull
+ private final NetworkTimeUpdateService mNetworkTimeUpdateService;
+
+ NetworkTimeUpdateServiceShellCommand(NetworkTimeUpdateService networkTimeUpdateService) {
+ mNetworkTimeUpdateService = Objects.requireNonNull(networkTimeUpdateService);
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ switch (cmd) {
+ case SHELL_COMMAND_CLEAR_TIME:
+ return runClearTime();
+ case SHELL_COMMAND_FORCE_REFRESH:
+ return runForceRefresh();
+ default: {
+ return handleDefaultCommands(cmd);
+ }
+ }
+ }
+
+ private int runClearTime() {
+ mNetworkTimeUpdateService.clearTimeForTests();
+ return 0;
+ }
+
+ private int runForceRefresh() {
+ boolean success = mNetworkTimeUpdateService.forceRefreshForTests();
+ getOutPrintWriter().println(success);
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.printf("Network Time Update Service (%s) commands:\n", SHELL_COMMAND_SERVICE_NAME);
+ pw.printf(" help\n");
+ pw.printf(" Print this help text.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_CLEAR_TIME);
+ pw.printf(" Clears the latest time.\n");
+ pw.printf(" %s\n", SHELL_COMMAND_FORCE_REFRESH);
+ pw.printf(" Refreshes the latest time. Prints whether it was successful.\n");
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 71b463a..f4b8f5d 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -23,14 +23,13 @@
per-file *AppOp* = file:/core/java/android/permission/OWNERS
per-file *Battery* = file:/BATTERY_STATS_OWNERS
per-file *Binder* = file:/core/java/com/android/internal/os/BINDER_OWNERS
-per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
per-file **IpSec* = file:/services/core/java/com/android/server/net/OWNERS
per-file **IpSec* = file:/services/core/java/com/android/server/vcn/OWNERS
per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS
per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
per-file *Storage* = file:/core/java/android/os/storage/OWNERS
-per-file *TimeUpdate* = file:/core/java/android/app/timezone/OWNERS
+per-file *TimeUpdate* = file:/services/core/java/com/android/server/timezonedetector/OWNERS
per-file DynamicSystemService.java = file:/packages/DynamicSystemInstallationService/OWNERS
per-file GestureLauncherService.java = file:platform/packages/apps/EmergencyInfo:/OWNERS
per-file MmsServiceBroker.java = file:/telephony/OWNERS
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 3cc8e76..f36d11e 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -20,6 +20,8 @@
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.UserInfo;
import android.os.Environment;
import android.os.SystemClock;
@@ -34,6 +36,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.SystemService.TargetUser;
import com.android.server.am.EventLogTags;
+import com.android.server.pm.ApexManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -42,6 +45,8 @@
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
/**
@@ -114,12 +119,31 @@
* @return The service instance.
*/
public SystemService startServiceFromJar(String className, String path) {
- PathClassLoader pathClassLoader = SystemServerClassLoaderFactory.getOrCreateClassLoader(
- path, this.getClass().getClassLoader());
+ PathClassLoader pathClassLoader =
+ SystemServerClassLoaderFactory.getOrCreateClassLoader(
+ path, this.getClass().getClassLoader(), isJarInTestApex(path));
final Class<SystemService> serviceClass = loadClassFromLoader(className, pathClassLoader);
return startService(serviceClass);
}
+ /**
+ * Returns true if the jar is in a test APEX.
+ */
+ private static boolean isJarInTestApex(String pathStr) {
+ Path path = Paths.get(pathStr);
+ if (path.getNameCount() >= 2 && path.getName(0).toString().equals("apex")) {
+ String apexModuleName = path.getName(1).toString();
+ ApexManager apexManager = ApexManager.getInstance();
+ String packageName = apexManager.getActivePackageNameForApexModuleName(apexModuleName);
+ PackageInfo packageInfo = apexManager.getPackageInfo(
+ packageName, ApexManager.MATCH_ACTIVE_PACKAGE);
+ if (packageInfo != null) {
+ return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0;
+ }
+ }
+ return false;
+ }
+
/*
* Loads and initializes a class from the given classLoader. Returns the class.
*/
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 6a7afd9..2d328d8 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -539,7 +539,13 @@
@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 @@
@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 @@
// 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 b48e21e..7b8cce5 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -340,17 +340,18 @@
* <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/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 6230919..583fb89 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -191,7 +191,9 @@
} else if (KEY_COMPACT_THROTTLE_1.equals(name)
|| KEY_COMPACT_THROTTLE_2.equals(name)
|| KEY_COMPACT_THROTTLE_3.equals(name)
- || KEY_COMPACT_THROTTLE_4.equals(name)) {
+ || KEY_COMPACT_THROTTLE_4.equals(name)
+ || KEY_COMPACT_THROTTLE_5.equals(name)
+ || KEY_COMPACT_THROTTLE_6.equals(name)) {
updateCompactionThrottles();
} else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
updateCompactStatsdSampleRate();
diff --git a/services/core/java/com/android/server/am/DataConnectionStats.java b/services/core/java/com/android/server/am/DataConnectionStats.java
index 6e39a4c..651e98c 100644
--- a/services/core/java/com/android/server/am/DataConnectionStats.java
+++ b/services/core/java/com/android/server/am/DataConnectionStats.java
@@ -73,7 +73,8 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SIM_STATE_CHANGED);
- mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler);
+ mContext.registerReceiver(this, filter, null /* broadcastPermission */, mListenerHandler,
+ Context.RECEIVER_NOT_EXPORTED);
}
@Override
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 2eb59b2..54987cf 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.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 @@
/*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 @@
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 @@
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 e00c8a3..4c56381 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.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;
@@ -2817,8 +2817,9 @@
int step;
// skip a2dp absolute volume control request when the device
- // is not an a2dp device
- if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ // is neither an a2dp device nor BLE device
+ if ((!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ && !AudioSystem.DEVICE_OUT_ALL_BLE_SET.contains(device))
&& (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
return;
}
@@ -2958,7 +2959,8 @@
}
if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
- && streamType == getBluetoothContextualVolumeStream()) {
+ && streamType == getBluetoothContextualVolumeStream()
+ && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
if (DEBUG_VOL) {
Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
+ newIndex + " stream=" + streamType);
@@ -3559,8 +3561,9 @@
int oldIndex;
// skip a2dp absolute volume control request when the device
- // is not an a2dp device
- if (!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ // is neither an a2dp device nor BLE device
+ if ((!AudioSystem.DEVICE_OUT_ALL_A2DP_SET.contains(device)
+ && !AudioSystem.DEVICE_OUT_ALL_BLE_SET.contains(device))
&& (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) != 0) {
return;
}
@@ -3602,7 +3605,8 @@
}
if (device == AudioSystem.DEVICE_OUT_BLE_HEADSET
- && streamType == getBluetoothContextualVolumeStream()) {
+ && streamType == getBluetoothContextualVolumeStream()
+ && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) {
if (DEBUG_VOL) {
Log.d(TAG, "adjustSreamVolume postSetLeAudioVolumeIndex index="
+ index + " stream=" + streamType);
@@ -6301,14 +6305,14 @@
* 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 9273a5d..4485c5b 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.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;
@@ -102,8 +102,6 @@
/*package*/ static final int SCO_MODE_UNDEFINED = -1;
// SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
/*package*/ static final int SCO_MODE_VIRTUAL_CALL = 0;
- // SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
- private static final int SCO_MODE_RAW = 1;
// SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition())
private static final int SCO_MODE_VR = 2;
// max valid SCO audio mode values
@@ -122,8 +120,6 @@
return "SCO_MODE_UNDEFINED";
case SCO_MODE_VIRTUAL_CALL:
return "SCO_MODE_VIRTUAL_CALL";
- case SCO_MODE_RAW:
- return "SCO_MODE_RAW";
case SCO_MODE_VR:
return "SCO_MODE_VR";
default:
@@ -482,6 +478,8 @@
}
if (profile == BluetoothProfile.A2DP) {
mA2dp = (BluetoothA2dp) proxy;
+ } else if (profile == BluetoothProfile.HEARING_AID) {
+ mHearingAid = (BluetoothHearingAid) proxy;
} else if (profile == BluetoothProfile.LE_AUDIO) {
mLeAudio = (BluetoothLeAudio) proxy;
}
@@ -490,16 +488,16 @@
return;
}
final BluetoothDevice btDevice = deviceList.get(0);
- final @BluetoothProfile.BtProfileState int state =
- proxy.getConnectionState(btDevice);
- if (state == BluetoothProfile.STATE_CONNECTED) {
+ if (proxy.getConnectionState(btDevice) == 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"));
}
}
@@ -812,8 +810,6 @@
private static boolean disconnectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset,
BluetoothDevice device, int scoAudioMode) {
switch (scoAudioMode) {
- case SCO_MODE_RAW:
- return bluetoothHeadset.disconnectAudio();
case SCO_MODE_VIRTUAL_CALL:
return bluetoothHeadset.stopScoUsingVirtualVoiceCall();
case SCO_MODE_VR:
@@ -826,8 +822,6 @@
private static boolean connectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset,
BluetoothDevice device, int scoAudioMode) {
switch (scoAudioMode) {
- case SCO_MODE_RAW:
- return bluetoothHeadset.connectAudio();
case SCO_MODE_VIRTUAL_CALL:
return bluetoothHeadset.startScoUsingVirtualVoiceCall();
case SCO_MODE_VR:
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 38df5f8..a0c5aa3 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -639,7 +639,7 @@
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/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 603f206..108e7bc 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -25,7 +25,6 @@
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.android.server.net.NetworkPolicyManagerInternal.QUOTA_TYPE_MULTIPATH;
import static com.android.server.net.NetworkPolicyManagerService.OPPORTUNISTIC_QUOTA_UNKNOWN;
@@ -191,6 +190,7 @@
class MultipathTracker {
final Network network;
final String subscriberId;
+ private final int mSubId;
private long mQuota;
/** Current multipath budget. Nonzero iff we have budget and a UsageCallback is armed. */
@@ -204,9 +204,8 @@
this.network = network;
this.mNetworkCapabilities = new NetworkCapabilities(nc);
NetworkSpecifier specifier = nc.getNetworkSpecifier();
- int subId = INVALID_SUBSCRIPTION_ID;
if (specifier instanceof TelephonyNetworkSpecifier) {
- subId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
+ mSubId = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
} else {
throw new IllegalStateException(String.format(
"Can't get subId from mobile network %s (%s)",
@@ -217,14 +216,14 @@
if (tele == null) {
throw new IllegalStateException(String.format("Missing TelephonyManager"));
}
- tele = tele.createForSubscriptionId(subId);
+ tele = tele.createForSubscriptionId(mSubId);
if (tele == null) {
throw new IllegalStateException(String.format(
- "Can't get TelephonyManager for subId %d", subId));
+ "Can't get TelephonyManager for subId %d", mSubId));
}
subscriberId = Objects.requireNonNull(tele.getSubscriberId(),
- "Null subscriber Id for subId " + subId);
+ "Null subscriber Id for subId " + mSubId);
mNetworkTemplate = new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
.setSubscriberIds(Set.of(subscriberId))
.setMeteredness(NetworkStats.METERED_YES)
@@ -282,6 +281,7 @@
.setSubscriberId(subscriberId)
.setRoaming(!nc.hasCapability(NET_CAPABILITY_NOT_ROAMING))
.setMetered(!nc.hasCapability(NET_CAPABILITY_NOT_METERED))
+ .setSubId(mSubId)
.build();
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9a9c3ea..30ae7d6 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.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 @@
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 @@
.setLegacyType(ConnectivityManager.TYPE_VPN)
.setLegacyTypeName("VPN")
.setBypassableVpn(mConfig.allowBypass && !mLockdown)
+ .setVpnRequiresValidation(mConfig.requiresInternetValidation)
.build();
capsBuilder.setOwnerUid(mOwnerUID);
@@ -2003,7 +2006,8 @@
.setCategory(Notification.CATEGORY_SYSTEM)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
- .setColor(mContext.getColor(R.color.system_notification_accent_color));
+ .setColor(mContext.getColor(
+ android.R.color.system_notification_accent_color));
notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build());
} finally {
Binder.restoreCallingIdentity(token);
@@ -2503,6 +2507,7 @@
mProfile = profile;
mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this);
+ mSessionKey = UUID.randomUUID().toString();
}
@Override
@@ -2824,6 +2829,7 @@
*/
private void disconnectVpnRunner() {
mActiveNetwork = null;
+ mSessionKey = null;
mIsRunning = false;
resetIkeState();
@@ -3314,7 +3320,7 @@
*
* @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 +3338,7 @@
}
startVpnProfilePrivileged(profile, packageName);
+ return mSessionKey;
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3363,6 +3370,7 @@
}
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 c27293c..c12522b 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 @@
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 @@
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 @@
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 0bb1285..c549b55 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 @@
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 37ee76b..4071858 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 @@
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 6e7a2a0..3d218cf 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 @@
@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 6f7473d..1c296e5 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 @@
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 @@
}
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 @@
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,6 +108,30 @@
addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander);
addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander);
+ addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
+ addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
+ addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
+ addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
+ addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
+ 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);
+
+ addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
+ addHandler(Constants.MESSAGE_ABORT, mBypasser);
+ addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
+
+ addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
+ 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>
@@ -124,24 +144,16 @@
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);
- addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
- addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
- addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser);
- addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBypasser);
- addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser);
+ public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDevice device) {
+ mService = service;
+ mDevice = device;
- addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
-
- addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
- addHandler(Constants.MESSAGE_ABORT, mBypasser);
- addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
-
- addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
- addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
+ addCommonHandlers();
+ if (mDevice.getType() == HdmiDeviceInfo.DEVICE_TV) {
+ addTvHandlers();
+ }
}
private void addHandler(int opcode, CecMessageHandler handler) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a571dc0..8dadf5a 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 @@
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 @@
}
@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 @@
}
}
- 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 @@
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/infra/OWNERS b/services/core/java/com/android/server/infra/OWNERS
new file mode 100644
index 0000000..0466d8a
--- /dev/null
+++ b/services/core/java/com/android/server/infra/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 655446
+
+include /core/java/android/service/cloudsearch/OWNERS
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3e52f5e..5b7f5c8 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 @@
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/locksettings/LockSettingsStrongAuth.java b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
index a102406..1203769 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
@@ -262,7 +262,7 @@
long nextAlarmTime = strongAuthTime + dpm.getRequiredStrongAuthTimeout(null, userId);
// schedule a new alarm listener for the user
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextAlarmTime,
STRONG_AUTH_TIMEOUT_ALARM_TAG, alarm, mHandler);
}
@@ -303,7 +303,7 @@
alarm = new NonStrongBiometricTimeoutAlarmListener(userId);
mNonStrongBiometricTimeoutAlarmListener.put(userId, alarm);
// schedule a new alarm listener for the user
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextAlarmTime,
NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG, alarm, mHandler);
}
@@ -394,7 +394,7 @@
}
// schedule a new alarm listener for the user
if (DEBUG) Slog.d(TAG, "Schedule a new alarm for non-strong biometric idle timeout");
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextAlarmTime,
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextAlarmTime,
NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG, alarm, mHandler);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 4822d6a..b482d18 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -62,6 +62,7 @@
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.NoSuchElementException;
/**
* This is the system implementation of a Session. Apps will interact with the
@@ -792,7 +793,10 @@
}
for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
try {
+ holder.mCallback.asBinder().unlinkToDeath(holder.mDeathMonitor, 0);
holder.mCallback.onSessionDestroyed();
+ } catch (NoSuchElementException e) {
+ logCallbackException("error unlinking to binder death", holder, e);
} catch (DeadObjectException e) {
logCallbackException("Removing dead callback in pushSessionDestroyed", holder, e);
} catch (RemoteException e) {
@@ -1375,12 +1379,22 @@
return;
}
if (getControllerHolderIndexForCb(cb) < 0) {
- mControllerCallbackHolders.add(new ISessionControllerCallbackHolder(cb,
- packageName, Binder.getCallingUid()));
+ ISessionControllerCallbackHolder holder = new ISessionControllerCallbackHolder(
+ cb, packageName, Binder.getCallingUid(), () -> unregisterCallback(cb));
+ mControllerCallbackHolders.add(holder);
if (DEBUG) {
Log.d(TAG, "registering controller callback " + cb + " from controller"
+ packageName);
}
+ // Avoid callback leaks
+ try {
+ // cb is not referenced outside of the MediaSessionRecord, so the death
+ // handler won't prevent MediaSessionRecord to be garbage collected.
+ cb.asBinder().linkToDeath(holder.mDeathMonitor, 0);
+ } catch (RemoteException e) {
+ unregisterCallback(cb);
+ Log.w(TAG, "registerCallback failed to linkToDeath", e);
+ }
}
}
}
@@ -1390,6 +1404,12 @@
synchronized (mLock) {
int index = getControllerHolderIndexForCb(cb);
if (index != -1) {
+ try {
+ cb.asBinder().unlinkToDeath(
+ mControllerCallbackHolders.get(index).mDeathMonitor, 0);
+ } catch (NoSuchElementException e) {
+ Log.w(TAG, "error unlinking to binder death", e);
+ }
mControllerCallbackHolders.remove(index);
}
if (DEBUG) {
@@ -1600,12 +1620,14 @@
private final ISessionControllerCallback mCallback;
private final String mPackageName;
private final int mUid;
+ private final IBinder.DeathRecipient mDeathMonitor;
ISessionControllerCallbackHolder(ISessionControllerCallback callback, String packageName,
- int uid) {
+ int uid, IBinder.DeathRecipient deathMonitor) {
mCallback = callback;
mPackageName = packageName;
mUid = uid;
+ mDeathMonitor = deathMonitor;
}
}
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 851ea3d..1b7d1ba 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -293,7 +293,7 @@
.addAction(R.drawable.ic_menu_refresh, mContext.getString(R.string.reset),
mResetIntent)
.setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color));
+ android.R.color.system_notification_accent_color));
mNotificationManager.notify(null /* tag */, SystemMessage.NOTE_VPN_STATUS,
builder.build());
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 81106b1..33ac6cd 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -15,13 +15,17 @@
*/
package com.android.server.net;
-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.ConnectivityManager.BLOCKED_REASON_NONE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.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_LOW_POWER_STANDBY;
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;
@@ -29,6 +33,7 @@
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 +86,18 @@
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);
+ }
}
}
@@ -320,6 +330,8 @@
return FIREWALL_CHAIN_NAME_POWERSAVE;
case FIREWALL_CHAIN_RESTRICTED:
return FIREWALL_CHAIN_NAME_RESTRICTED;
+ case FIREWALL_CHAIN_LOW_POWER_STANDBY:
+ return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
default:
return String.valueOf(chain);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 6a00d06..9f58f65 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -61,7 +61,6 @@
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
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.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -173,11 +172,9 @@
import android.net.NetworkPolicyManager;
import android.net.NetworkPolicyManager.UidState;
import android.net.NetworkRequest;
-import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStateSnapshot;
import android.net.NetworkTemplate;
-import android.net.TelephonyNetworkSpecifier;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.BestClock;
@@ -284,6 +281,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.IntConsumer;
@@ -1006,10 +1004,11 @@
mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
// listen for stats updated callbacks for interested network types.
+ final Executor executor = new HandlerExecutor(mHandler);
mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_MOBILE).build(),
- 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
+ 0 /* thresholdBytes */, executor, mStatsCallback);
mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_WIFI).build(),
- 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
+ 0 /* thresholdBytes */, executor, mStatsCallback);
// listen for restrict background changes from notifications
final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
@@ -1237,6 +1236,12 @@
* Used to determine if NetworkStatsService is ready.
*/
public boolean isAnyCallbackReceived() {
+ // Warning : threading for this member is broken. It should only be read
+ // and written on the handler thread ; furthermore, the constructor
+ // is called on a different thread, so this stops working if the default
+ // value is not false or if this member ever goes back to false after
+ // being set to true.
+ // TODO : fix threading for this member.
return mIsAnyCallbackReceived;
}
};
@@ -1512,7 +1517,8 @@
.setType(TYPE_MOBILE)
.setSubscriberId(subscriberId)
.setMetered(true)
- .setDefaultNetwork(true).build();
+ .setDefaultNetwork(true)
+ .setSubId(subId).build();
if (template.matches(probeIdent)) {
return subId;
}
@@ -1749,7 +1755,8 @@
.setType(TYPE_MOBILE)
.setSubscriberId(subscriberId)
.setMetered(true)
- .setDefaultNetwork(true).build();
+ .setDefaultNetwork(true)
+ .setSubId(subId).build();
for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
final NetworkTemplate template = mNetworkPolicy.keyAt(i);
if (template.matches(probeIdent)) {
@@ -1981,7 +1988,8 @@
.setType(TYPE_MOBILE)
.setSubscriberId(subscriberId)
.setMetered(true)
- .setDefaultNetwork(true).build();
+ .setDefaultNetwork(true)
+ .setSubId(subId).build();
// Template is matched when subscriber id matches.
if (template.matches(probeIdent)) {
matchingSubIds.add(subId);
@@ -2083,7 +2091,8 @@
mNetIdToSubId.clear();
final ArrayMap<NetworkStateSnapshot, NetworkIdentity> identified = new ArrayMap<>();
for (final NetworkStateSnapshot snapshot : snapshots) {
- mNetIdToSubId.put(snapshot.getNetwork().getNetId(), parseSubId(snapshot));
+ final int subId = snapshot.getSubId();
+ mNetIdToSubId.put(snapshot.getNetwork().getNetId(), subId);
// Policies matched by NPMS only match by subscriber ID or by network ID.
final NetworkIdentity ident = new NetworkIdentity.Builder()
@@ -2288,7 +2297,8 @@
.setType(TYPE_MOBILE)
.setSubscriberId(subscriberId)
.setMetered(true)
- .setDefaultNetwork(true).build();
+ .setDefaultNetwork(true)
+ .setSubId(subId).build();
for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
final NetworkTemplate template = mNetworkPolicy.keyAt(i);
if (template.matches(probeIdent)) {
@@ -5807,17 +5817,6 @@
}
}
- private int parseSubId(@NonNull NetworkStateSnapshot snapshot) {
- int subId = INVALID_SUBSCRIPTION_ID;
- if (snapshot.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR)) {
- NetworkSpecifier spec = snapshot.getNetworkCapabilities().getNetworkSpecifier();
- if (spec instanceof TelephonyNetworkSpecifier) {
- subId = ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
- }
- }
- return subId;
- }
-
@GuardedBy("mNetworkPoliciesSecondLock")
private int getSubIdLocked(Network network) {
return mNetIdToSubId.get(network.getNetId(), INVALID_SUBSCRIPTION_ID);
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 31b1860..e7e691c 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -343,6 +343,13 @@
public abstract String getApexModuleNameForPackageName(String apexPackageName);
/**
+ * Returns the package name of the active APEX whose name is {@code apexModuleName}. If not
+ * found, returns {@code null}.
+ */
+ @Nullable
+ public abstract String getActivePackageNameForApexModuleName(String apexModuleName);
+
+ /**
* Copies the CE apex data directory for the given {@code userId} to a backup location, for use
* in case of rollback.
*
@@ -467,6 +474,12 @@
private ArrayMap<String, String> mPackageNameToApexModuleName;
/**
+ * Reverse mapping of {@link #mPackageNameToApexModuleName}, for active packages only.
+ */
+ @GuardedBy("mLock")
+ private ArrayMap<String, String> mApexModuleNameToActivePackageName;
+
+ /**
* Whether an APEX package is active or not.
*
* @param packageInfo the package to check
@@ -534,6 +547,7 @@
try {
mAllPackagesCache = new ArrayList<>();
mPackageNameToApexModuleName = new ArrayMap<>();
+ mApexModuleNameToActivePackageName = new ArrayMap<>();
allPkgs = waitForApexService().getAllPackages();
} catch (RemoteException re) {
Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
@@ -580,6 +594,13 @@
+ packageInfo.packageName);
}
activePackagesSet.add(packageInfo.packageName);
+ if (mApexModuleNameToActivePackageName.containsKey(ai.moduleName)) {
+ throw new IllegalStateException(
+ "Two active packages have the same APEX module name: "
+ + ai.moduleName);
+ }
+ mApexModuleNameToActivePackageName.put(
+ ai.moduleName, packageInfo.packageName);
}
if (ai.isFactory) {
// Don't throw when the duplicating APEX is VNDK APEX
@@ -913,6 +934,16 @@
}
@Override
+ @Nullable
+ public String getActivePackageNameForApexModuleName(String apexModuleName) {
+ synchronized (mLock) {
+ Preconditions.checkState(mApexModuleNameToActivePackageName != null,
+ "APEX packages have not been scanned");
+ return mApexModuleNameToActivePackageName.get(apexModuleName);
+ }
+ }
+
+ @Override
public boolean snapshotCeData(int userId, int rollbackId, String apexPackageName) {
String apexModuleName;
synchronized (mLock) {
@@ -1330,6 +1361,12 @@
}
@Override
+ @Nullable
+ public String getActivePackageNameForApexModuleName(String apexModuleName) {
+ return null;
+ }
+
+ @Override
public boolean snapshotCeData(int userId, int rollbackId, String apexPackageName) {
throw new UnsupportedOperationException();
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 8fd545f..5a5f9ef 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 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 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 bc28cff..bc6c306 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 @@
* 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 @@
}
/**
- * 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,
@@ -12935,7 +12908,8 @@
DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES |
DexoptOptions.DEXOPT_BOOT_COMPLETE |
(force ? DexoptOptions.DEXOPT_FORCE : 0);
- return performDexOpt(new DexoptOptions(packageName, compilerFilter, flags));
+ return performDexOpt(new DexoptOptions(packageName, REASON_CMDLINE,
+ compilerFilter, /* splitName */ null, flags));
}
/*package*/ boolean performDexOpt(DexoptOptions options) {
@@ -21192,9 +21166,7 @@
*/
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 +21177,25 @@
// 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 +21204,14 @@
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 8b5abf3..8970049 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 @@
/** 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 @@
== 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/parsing/library/ApexSharedLibraryUpdater.java b/services/core/java/com/android/server/pm/parsing/library/ApexSharedLibraryUpdater.java
new file mode 100644
index 0000000..0418afb
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/library/ApexSharedLibraryUpdater.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.parsing.library;
+
+import android.util.ArrayMap;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.SystemConfig;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+/**
+ * Updates packages to add or remove dependencies on shared libraries as per attributes
+ * in the library declaration
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class ApexSharedLibraryUpdater extends PackageSharedLibraryUpdater {
+
+ /**
+ * ArrayMap like the one you find in {@link SystemConfig}. The keys are the library names.
+ */
+ private final ArrayMap<String, SystemConfig.SharedLibraryEntry> mSharedLibraries;
+
+ public ApexSharedLibraryUpdater(
+ ArrayMap<String, SystemConfig.SharedLibraryEntry> sharedLibraries) {
+ mSharedLibraries = sharedLibraries;
+ }
+
+ @Override
+ public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
+ final int builtInLibCount = mSharedLibraries.size();
+ for (int i = 0; i < builtInLibCount; i++) {
+ updateSharedLibraryForPackage(mSharedLibraries.valueAt(i), parsedPackage);
+ }
+ }
+
+ private void updateSharedLibraryForPackage(SystemConfig.SharedLibraryEntry entry,
+ ParsedPackage parsedPackage) {
+ if (entry.onBootclasspathBefore != 0
+ && parsedPackage.getTargetSdkVersion() < entry.onBootclasspathBefore) {
+ // this package targets an API where this library was in the BCP, so add
+ // the library transparently in case the package is using it
+ prefixRequiredLibrary(parsedPackage, entry.name);
+ }
+
+ if (entry.canBeSafelyIgnored) {
+ // the library is now present in the BCP and always available; we don't need to add
+ // it a second time
+ removeLibrary(parsedPackage, entry.name);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
index 8a8a302..d81e7d0 100644
--- a/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
+++ b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
@@ -25,6 +25,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.SystemConfig;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import java.util.ArrayList;
@@ -63,6 +64,11 @@
boolean bootClassPathContainsATB = !addUpdaterForAndroidTestBase(packageUpdaters);
+ // ApexSharedLibraryUpdater should be the last one, to allow modifications introduced by
+ // mainline after dessert release.
+ packageUpdaters.add(new ApexSharedLibraryUpdater(
+ SystemConfig.getInstance().getSharedLibraries()));
+
PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
.toArray(new PackageSharedLibraryUpdater[0]);
INSTANCE = new PackageBackwardCompatibility(
@@ -106,6 +112,11 @@
private final PackageSharedLibraryUpdater[] mPackageUpdaters;
+ @VisibleForTesting
+ PackageSharedLibraryUpdater[] getPackageUpdaters() {
+ return mPackageUpdaters;
+ }
+
private PackageBackwardCompatibility(
boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) {
this.mBootClassPathContainsATB = bootClassPathContainsATB;
diff --git a/services/core/java/com/android/server/policy/KeyCombinationManager.java b/services/core/java/com/android/server/policy/KeyCombinationManager.java
index 268de3e..68e078c 100644
--- a/services/core/java/com/android/server/policy/KeyCombinationManager.java
+++ b/services/core/java/com/android/server/policy/KeyCombinationManager.java
@@ -17,11 +17,13 @@
import static android.view.KeyEvent.KEYCODE_POWER;
+import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseLongArray;
import android.view.KeyEvent;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ToBooleanFunction;
import java.io.PrintWriter;
@@ -35,13 +37,18 @@
private static final String TAG = "KeyCombinationManager";
// Store the received down time of keycode.
+ @GuardedBy("mLock")
private final SparseLongArray mDownTimes = new SparseLongArray(2);
private final ArrayList<TwoKeysCombinationRule> mRules = new ArrayList();
// Selected rules according to current key down.
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
private final ArrayList<TwoKeysCombinationRule> mActiveRules = new ArrayList();
// The rule has been triggered by current keys.
+ @GuardedBy("mLock")
private TwoKeysCombinationRule mTriggeredRule;
+ private final Handler mHandler = new Handler();
// Keys in a key combination must be pressed within this interval of each other.
private static final long COMBINE_KEY_DELAY_MILLIS = 150;
@@ -109,6 +116,12 @@
* Return true if any active rule could be triggered by the key event, otherwise false.
*/
boolean interceptKey(KeyEvent event, boolean interactive) {
+ synchronized (mLock) {
+ return interceptKeyLocked(event, interactive);
+ }
+ }
+
+ private boolean interceptKeyLocked(KeyEvent event, boolean interactive) {
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final int keyCode = event.getKeyCode();
final int count = mActiveRules.size();
@@ -154,7 +167,7 @@
return false;
}
Log.v(TAG, "Performing combination rule : " + rule);
- rule.execute();
+ mHandler.post(rule::execute);
mTriggeredRule = rule;
return true;
});
@@ -169,7 +182,7 @@
for (int index = count - 1; index >= 0; index--) {
final TwoKeysCombinationRule rule = mActiveRules.get(index);
if (rule.shouldInterceptKey(keyCode)) {
- rule.cancel();
+ mHandler.post(rule::cancel);
mActiveRules.remove(index);
}
}
@@ -181,31 +194,37 @@
* Return the interceptTimeout to tell InputDispatcher when is ready to deliver to window.
*/
long getKeyInterceptTimeout(int keyCode) {
- if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
- return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
+ synchronized (mLock) {
+ if (forAllActiveRules((rule) -> rule.shouldInterceptKey(keyCode))) {
+ return mDownTimes.get(keyCode) + COMBINE_KEY_DELAY_MILLIS;
+ }
+ return 0;
}
- return 0;
}
/**
* True if the key event had been handled.
*/
boolean isKeyConsumed(KeyEvent event) {
- if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
- return false;
+ synchronized (mLock) {
+ if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) != 0) {
+ return false;
+ }
+ return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
}
- return mTriggeredRule != null && mTriggeredRule.shouldInterceptKey(event.getKeyCode());
}
/**
* True if power key is the candidate.
*/
boolean isPowerKeyIntercepted() {
- if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
- // return false if only if power key pressed.
- return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
+ synchronized (mLock) {
+ if (forAllActiveRules((rule) -> rule.shouldInterceptKey(KEYCODE_POWER))) {
+ // return false if only if power key pressed.
+ return mDownTimes.size() > 1 || mDownTimes.get(KEYCODE_POWER) == 0;
+ }
+ return false;
}
- return false;
}
/**
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 1fa948c..9cf38e3 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -2609,6 +2609,7 @@
StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
+ StatFs metadataFsSystem = new StatFs(Environment.getMetadataDirectory().getAbsolutePath());
pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__DATA, statFsData.getAvailableBytes(),
@@ -2621,6 +2622,10 @@
pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__SYSTEM,
statFsSystem.getAvailableBytes(), statFsSystem.getTotalBytes()));
+
+ pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
+ FrameworkStatsLog.DIRECTORY_USAGE__DIRECTORY__METADATA,
+ metadataFsSystem.getAvailableBytes(), metadataFsSystem.getTotalBytes()));
return StatsManager.PULL_SUCCESS;
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 357c232..ae4d46c 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -69,7 +69,7 @@
* Telephony and network suggestions older than this value are considered too old to be used.
*/
@VisibleForTesting
- static final long MAX_UTC_TIME_AGE_MILLIS =
+ static final long MAX_SUGGESTION_TIME_AGE_MILLIS =
TELEPHONY_BUCKET_COUNT * TELEPHONY_BUCKET_SIZE_MILLIS;
/**
@@ -204,9 +204,9 @@
@Override
public synchronized void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
- final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
+ final TimestampedValue<Long> newUnixEpochTime = timeSuggestion.getUnixEpochTime();
- if (!validateAutoSuggestionTime(newUtcTime, timeSuggestion)) {
+ if (!validateAutoSuggestionTime(newUnixEpochTime, timeSuggestion)) {
return;
}
@@ -218,9 +218,9 @@
@Override
public synchronized void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion) {
- final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
+ final TimestampedValue<Long> newUnixEpochTime = timeSuggestion.getUnixEpochTime();
- if (!validateAutoSuggestionTime(newUtcTime, timeSuggestion)) {
+ if (!validateAutoSuggestionTime(newUnixEpochTime, timeSuggestion)) {
return;
}
@@ -232,19 +232,19 @@
@Override
public synchronized boolean suggestManualTime(@NonNull ManualTimeSuggestion suggestion) {
- final TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
+ final TimestampedValue<Long> newUnixEpochTime = suggestion.getUnixEpochTime();
- if (!validateSuggestionTime(newUtcTime, suggestion)) {
+ if (!validateSuggestionTime(newUnixEpochTime, suggestion)) {
return false;
}
String cause = "Manual time suggestion received: suggestion=" + suggestion;
- return setSystemClockIfRequired(ORIGIN_MANUAL, newUtcTime, cause);
+ return setSystemClockIfRequired(ORIGIN_MANUAL, newUnixEpochTime, cause);
}
@Override
public synchronized void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion) {
- if (!validateAutoSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) {
+ if (!validateAutoSuggestionTime(timeSuggestion.getUnixEpochTime(), timeSuggestion)) {
return;
}
@@ -274,11 +274,11 @@
// unlike time zone, where a user may lose connectivity when boarding a flight and where we
// do want to "forget" old signals. Suggestions that are too old are discarded later in the
// detection algorithm.
- if (timeSuggestion.getUtcTime() == null) {
+ if (timeSuggestion.getUnixEpochTime() == null) {
return;
}
- if (!validateAutoSuggestionTime(timeSuggestion.getUtcTime(), timeSuggestion)) {
+ if (!validateAutoSuggestionTime(timeSuggestion.getUnixEpochTime(), timeSuggestion)) {
return;
}
@@ -365,14 +365,14 @@
@GuardedBy("this")
private boolean storeTelephonySuggestion(
@NonNull TelephonyTimeSuggestion suggestion) {
- TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
+ TimestampedValue<Long> newUnixEpochTime = suggestion.getUnixEpochTime();
int slotIndex = suggestion.getSlotIndex();
TelephonyTimeSuggestion previousSuggestion = mSuggestionBySlotIndex.get(slotIndex);
if (previousSuggestion != null) {
// We can log / discard suggestions with obvious issues with the reference time clock.
- if (previousSuggestion.getUtcTime() == null
- || previousSuggestion.getUtcTime().getValue() == null) {
+ if (previousSuggestion.getUnixEpochTime() == null
+ || previousSuggestion.getUnixEpochTime().getValue() == null) {
// This should be impossible given we only store validated suggestions.
Slog.w(LOG_TAG, "Previous suggestion is null or has a null time."
+ " previousSuggestion=" + previousSuggestion
@@ -381,7 +381,7 @@
}
long referenceTimeDifference = TimestampedValue.referenceTimeDifference(
- newUtcTime, previousSuggestion.getUtcTime());
+ newUnixEpochTime, previousSuggestion.getUnixEpochTime());
if (referenceTimeDifference < 0) {
// The reference time is before the previously received suggestion. Ignore it.
Slog.w(LOG_TAG, "Out of order telephony suggestion received."
@@ -398,15 +398,15 @@
}
private boolean validateSuggestionTime(
- @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) {
- if (newUtcTime.getValue() == null) {
+ @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
+ if (newUnixEpochTime.getValue() == null) {
Slog.w(LOG_TAG, "Suggested time value is null. suggestion=" + suggestion);
return false;
}
// We can validate the suggestion against the reference time clock.
long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
- if (elapsedRealtimeMillis < newUtcTime.getReferenceTimeMillis()) {
+ if (elapsedRealtimeMillis < newUnixEpochTime.getReferenceTimeMillis()) {
// elapsedRealtime clock went backwards?
Slog.w(LOG_TAG, "New reference time is in the future? Ignoring."
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
@@ -417,17 +417,17 @@
}
private boolean validateAutoSuggestionTime(
- @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) {
- return validateSuggestionTime(newUtcTime, suggestion)
- && validateSuggestionAgainstLowerBound(newUtcTime, suggestion);
+ @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
+ return validateSuggestionTime(newUnixEpochTime, suggestion)
+ && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion);
}
private boolean validateSuggestionAgainstLowerBound(
- @NonNull TimestampedValue<Long> newUtcTime, @NonNull Object suggestion) {
+ @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
Instant lowerBound = mEnvironment.autoTimeLowerBound();
// Suggestion is definitely wrong if it comes before lower time bound.
- if (lowerBound.isAfter(Instant.ofEpochMilli(newUtcTime.getValue()))) {
+ if (lowerBound.isAfter(Instant.ofEpochMilli(newUnixEpochTime.getValue()))) {
Slog.w(LOG_TAG, "Suggestion points to time before lower bound, skipping it. "
+ "suggestion=" + suggestion + ", lower bound=" + lowerBound);
return false;
@@ -446,12 +446,12 @@
// Try the different origins one at a time.
int[] originPriorities = mEnvironment.autoOriginPriorities();
for (int origin : originPriorities) {
- TimestampedValue<Long> newUtcTime = null;
+ TimestampedValue<Long> newUnixEpochTime = null;
String cause = null;
if (origin == ORIGIN_TELEPHONY) {
TelephonyTimeSuggestion bestTelephonySuggestion = findBestTelephonySuggestion();
if (bestTelephonySuggestion != null) {
- newUtcTime = bestTelephonySuggestion.getUtcTime();
+ newUnixEpochTime = bestTelephonySuggestion.getUnixEpochTime();
cause = "Found good telephony suggestion."
+ ", bestTelephonySuggestion=" + bestTelephonySuggestion
+ ", detectionReason=" + detectionReason;
@@ -459,7 +459,7 @@
} else if (origin == ORIGIN_NETWORK) {
NetworkTimeSuggestion networkSuggestion = findLatestValidNetworkSuggestion();
if (networkSuggestion != null) {
- newUtcTime = networkSuggestion.getUtcTime();
+ newUnixEpochTime = networkSuggestion.getUnixEpochTime();
cause = "Found good network suggestion."
+ ", networkSuggestion=" + networkSuggestion
+ ", detectionReason=" + detectionReason;
@@ -467,7 +467,7 @@
} else if (origin == ORIGIN_GNSS) {
GnssTimeSuggestion gnssTimeSuggestion = findLatestValidGnssSuggestion();
if (gnssTimeSuggestion != null) {
- newUtcTime = gnssTimeSuggestion.getUtcTime();
+ newUnixEpochTime = gnssTimeSuggestion.getUnixEpochTime();
cause = "Found good gnss suggestion."
+ ", gnssTimeSuggestion=" + gnssTimeSuggestion
+ ", detectionReason=" + detectionReason;
@@ -475,7 +475,7 @@
} else if (origin == ORIGIN_EXTERNAL) {
ExternalTimeSuggestion externalTimeSuggestion = findLatestValidExternalSuggestion();
if (externalTimeSuggestion != null) {
- newUtcTime = externalTimeSuggestion.getUtcTime();
+ newUnixEpochTime = externalTimeSuggestion.getUnixEpochTime();
cause = "Found good external suggestion."
+ ", externalTimeSuggestion=" + externalTimeSuggestion
+ ", detectionReason=" + detectionReason;
@@ -487,8 +487,8 @@
}
// Update the system clock if a good suggestion has been found.
- if (newUtcTime != null) {
- setSystemClockIfRequired(origin, newUtcTime, cause);
+ if (newUnixEpochTime != null) {
+ setSystemClockIfRequired(origin, newUnixEpochTime, cause);
return;
}
}
@@ -545,7 +545,7 @@
Slog.w(LOG_TAG, "Latest suggestion unexpectedly null for slotIndex."
+ " slotIndex=" + slotIndex);
continue;
- } else if (candidateSuggestion.getUtcTime() == null) {
+ } else if (candidateSuggestion.getUnixEpochTime() == null) {
// Unexpected - we do not store empty suggestions.
Slog.w(LOG_TAG, "Latest suggestion unexpectedly empty. "
+ " candidateSuggestion=" + candidateSuggestion);
@@ -579,8 +579,8 @@
long elapsedRealtimeMillis, @NonNull TelephonyTimeSuggestion timeSuggestion) {
// Validate first.
- TimestampedValue<Long> utcTime = timeSuggestion.getUtcTime();
- if (!validateSuggestionUtcTime(elapsedRealtimeMillis, utcTime)) {
+ TimestampedValue<Long> unixEpochTime = timeSuggestion.getUnixEpochTime();
+ if (!validateSuggestionUnixEpochTime(elapsedRealtimeMillis, unixEpochTime)) {
Slog.w(LOG_TAG, "Existing suggestion found to be invalid"
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ ", timeSuggestion=" + timeSuggestion);
@@ -589,7 +589,7 @@
// The score is based on the age since receipt. Suggestions are bucketed so two
// suggestions in the same bucket from different slotIndexs are scored the same.
- long ageMillis = elapsedRealtimeMillis - utcTime.getReferenceTimeMillis();
+ long ageMillis = elapsedRealtimeMillis - unixEpochTime.getReferenceTimeMillis();
// Turn the age into a discrete value: 0 <= bucketIndex < TELEPHONY_BUCKET_COUNT.
int bucketIndex = (int) (ageMillis / TELEPHONY_BUCKET_SIZE_MILLIS);
@@ -611,9 +611,9 @@
return null;
}
- TimestampedValue<Long> utcTime = networkSuggestion.getUtcTime();
+ TimestampedValue<Long> unixEpochTime = networkSuggestion.getUnixEpochTime();
long elapsedRealTimeMillis = mEnvironment.elapsedRealtimeMillis();
- if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) {
+ if (!validateSuggestionUnixEpochTime(elapsedRealTimeMillis, unixEpochTime)) {
// The latest suggestion is not valid, usually due to its age.
return null;
}
@@ -631,9 +631,9 @@
return null;
}
- TimestampedValue<Long> utcTime = gnssTimeSuggestion.getUtcTime();
+ TimestampedValue<Long> unixEpochTime = gnssTimeSuggestion.getUnixEpochTime();
long elapsedRealTimeMillis = mEnvironment.elapsedRealtimeMillis();
- if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) {
+ if (!validateSuggestionUnixEpochTime(elapsedRealTimeMillis, unixEpochTime)) {
// The latest suggestion is not valid, usually due to its age.
return null;
}
@@ -651,9 +651,9 @@
return null;
}
- TimestampedValue<Long> utcTime = externalTimeSuggestion.getUtcTime();
+ TimestampedValue<Long> unixEpochTime = externalTimeSuggestion.getUnixEpochTime();
long elapsedRealTimeMillis = mEnvironment.elapsedRealtimeMillis();
- if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) {
+ if (!validateSuggestionUnixEpochTime(elapsedRealTimeMillis, unixEpochTime)) {
// The latest suggestion is not valid, usually due to its age.
return null;
}
@@ -844,9 +844,9 @@
return mLastExternalSuggestion.get();
}
- private static boolean validateSuggestionUtcTime(
- long elapsedRealtimeMillis, TimestampedValue<Long> utcTime) {
- long referenceTimeMillis = utcTime.getReferenceTimeMillis();
+ private static boolean validateSuggestionUnixEpochTime(
+ long elapsedRealtimeMillis, TimestampedValue<Long> unixEpochTime) {
+ long referenceTimeMillis = unixEpochTime.getReferenceTimeMillis();
if (referenceTimeMillis > elapsedRealtimeMillis) {
// Future reference times are ignored. They imply the reference time was wrong, or the
// elapsed realtime clock used to derive it has gone backwards, neither of which are
@@ -860,6 +860,6 @@
// made and never replaced, it could also mean that the time detection code remains
// opinionated using a bad invalid suggestion. This caps that edge case at MAX_AGE_MILLIS.
long ageMillis = elapsedRealtimeMillis - referenceTimeMillis;
- return ageMillis <= MAX_UTC_TIME_AGE_MILLIS;
+ return ageMillis <= MAX_SUGGESTION_TIME_AGE_MILLIS;
}
}
diff --git a/services/core/java/com/android/server/timezonedetector/OWNERS b/services/core/java/com/android/server/timezonedetector/OWNERS
index 0293242..485a0dd 100644
--- a/services/core/java/com/android/server/timezonedetector/OWNERS
+++ b/services/core/java/com/android/server/timezonedetector/OWNERS
@@ -3,5 +3,6 @@
# ultimately referenced by other OWNERS files for components maintained by the same team.
nfuller@google.com
jmorace@google.com
+kanyinsola@google.com
mingaleev@google.com
narayan@google.com
diff --git a/services/core/java/com/android/server/tracing/TracingServiceProxy.java b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
index 27c0bee..10e868d 100644
--- a/services/core/java/com/android/server/tracing/TracingServiceProxy.java
+++ b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
@@ -15,6 +15,13 @@
*/
package com.android.server.tracing;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BEGIN;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BIND_PERM_INCORRECT;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_COMM_ERROR;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_HANDOFF;
+import static com.android.internal.util.FrameworkStatsLog.TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_PERM_MISSING;
+
import android.Manifest;
import android.annotation.NonNull;
import android.content.ComponentName;
@@ -39,6 +46,7 @@
import android.util.Slog;
import com.android.internal.infra.ServiceConnector;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.server.SystemService;
import java.io.IOException;
@@ -71,6 +79,17 @@
private static final String INTENT_ACTION_NOTIFY_SESSION_STOLEN =
"com.android.traceur.NOTIFY_SESSION_STOLEN";
+ private static final int REPORT_BEGIN =
+ TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BEGIN;
+ private static final int REPORT_SVC_HANDOFF =
+ TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_HANDOFF;
+ private static final int REPORT_BIND_PERM_INCORRECT =
+ TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_BIND_PERM_INCORRECT;
+ private static final int REPORT_SVC_PERM_MISSING =
+ TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_PERM_MISSING;
+ private static final int REPORT_SVC_COMM_ERROR =
+ TRACING_SERVICE_REPORT_EVENT__EVENT__TRACING_SERVICE_REPORT_SVC_COMM_ERROR;
+
private final Context mContext;
private final PackageManager mPackageManager;
private final LruCache<ComponentName, ServiceConnector<IMessenger>> mCachedReporterServices;
@@ -134,17 +153,24 @@
}
private void reportTrace(@NonNull TraceReportParams params) {
+ FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_BEGIN,
+ params.uuidLsb, params.uuidMsb);
+
// 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)) {
+ FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_BIND_PERM_INCORRECT,
+ params.uuidLsb, params.uuidMsb);
return;
}
boolean hasDumpPermission = hasPermission(component, Manifest.permission.DUMP);
boolean hasUsageStatsPermission = hasPermission(component,
Manifest.permission.PACKAGE_USAGE_STATS);
if (!hasDumpPermission || !hasUsageStatsPermission) {
+ FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_SVC_PERM_MISSING,
+ params.uuidLsb, params.uuidMsb);
return;
}
final long ident = Binder.clearCallingIdentity();
@@ -178,8 +204,13 @@
message.what = TraceReportService.MSG_REPORT_TRACE;
message.obj = params;
messenger.send(message);
+
+ FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_SVC_HANDOFF,
+ params.uuidLsb, params.uuidMsb);
}).whenComplete((res, err) -> {
if (err != null) {
+ FrameworkStatsLog.write(TRACING_SERVICE_REPORT_EVENT, REPORT_SVC_COMM_ERROR,
+ params.uuidLsb, params.uuidMsb);
Slog.e(TAG, "Failed to report trace", err);
}
try {
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index a17e792..30e2617 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -146,7 +146,7 @@
filter.addAction(ACTION_CARRIER_CONFIG_CHANGED);
filter.addAction(ACTION_MULTI_SIM_CONFIG_CHANGED);
- mContext.registerReceiver(this, filter, null, mHandler);
+ mContext.registerReceiver(this, filter, null, mHandler, Context.RECEIVER_NOT_EXPORTED);
mSubscriptionManager.addOnSubscriptionsChangedListener(
executor, mSubscriptionChangedListener);
mTelephonyManager.registerTelephonyCallback(executor, mActiveDataSubIdListener);
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 8b80b4a..597f7f2 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -78,6 +78,7 @@
import android.os.Process;
import android.os.SystemClock;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.Slog;
@@ -163,6 +164,14 @@
public class VcnGatewayConnection extends StateMachine {
private static final String TAG = VcnGatewayConnection.class.getSimpleName();
+ // Matches DataConnection.NETWORK_TYPE private constant, and magic string from
+ // ConnectivityManager#getNetworkTypeName()
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final String NETWORK_INFO_NETWORK_TYPE_STRING = "MOBILE";
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final String NETWORK_INFO_EXTRA_INFO = "VCN";
+
@VisibleForTesting(visibility = Visibility.PRIVATE)
static final InetAddress DUMMY_ADDR = InetAddresses.parseNumericAddress("192.0.2.0");
@@ -1631,6 +1640,12 @@
final NetworkAgentConfig nac =
new NetworkAgentConfig.Builder()
.setLegacyType(ConnectivityManager.TYPE_MOBILE)
+ .setLegacyTypeName(NETWORK_INFO_NETWORK_TYPE_STRING)
+ .setLegacySubType(TelephonyManager.NETWORK_TYPE_UNKNOWN)
+ .setLegacySubTypeName(
+ TelephonyManager.getNetworkTypeName(
+ TelephonyManager.NETWORK_TYPE_UNKNOWN))
+ .setLegacyExtraInfo(NETWORK_INFO_EXTRA_INFO)
.build();
final VcnNetworkAgent agent =
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b52e527..b685d48 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 @@
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 @@
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/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index f61cc94..a83a033 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -65,7 +65,16 @@
@Override
public void binderDied() {
synchronized (mGlobalLock) {
- mOrganizersByFeatureIds.remove(mFeature).destroy();
+ IDisplayAreaOrganizer featureOrganizer = getOrganizerByFeature(mFeature);
+ if (featureOrganizer != null) {
+ IBinder organizerBinder = featureOrganizer.asBinder();
+ if (!organizerBinder.equals(mOrganizer.asBinder()) &&
+ organizerBinder.isBinderAlive()) {
+ Slog.d(TAG, "Dead organizer replaced for feature=" + mFeature);
+ return;
+ }
+ mOrganizersByFeatureIds.remove(mFeature).destroy();
+ }
}
}
}
@@ -172,7 +181,7 @@
organizer.asBinder(), uid);
mOrganizersByFeatureIds.entrySet().removeIf((entry) -> {
final boolean matches = entry.getValue().mOrganizer.asBinder()
- == organizer.asBinder();
+ .equals(organizer.asBinder());
if (matches) {
entry.getValue().destroy();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9335846..bb8d6ef 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 @@
* 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/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index ee4c629..152b4bc 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -42,13 +42,12 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static java.lang.Integer.MIN_VALUE;
-
import android.annotation.ColorInt;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.content.res.Configuration;
+import android.graphics.Color;
import android.os.UserHandle;
import android.util.IntArray;
import android.util.Slog;
@@ -83,9 +82,9 @@
DisplayContent mDisplayContent;
/**
- * A color layer that serves as a solid color background to certain animations.
+ * Keeps track of the last set color layer so that it can be reset during surface migrations.
*/
- private SurfaceControl mColorBackgroundLayer;
+ private @ColorInt int mBackgroundColor = 0;
/**
* This counter is used to make sure we don't prematurely clear the background color in the
@@ -367,6 +366,14 @@
}
@Override
+ void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
+ // We want an effect layer instead of the default container layer so that we can set a
+ // background color on it for task animations.
+ b.setEffectLayer();
+ super.setInitialSurfaceControlProperties(b);
+ }
+
+ @Override
void addChild(WindowContainer child, int position) {
if (child.asTaskDisplayArea() != null) {
if (DEBUG_ROOT_TASK) {
@@ -980,11 +987,6 @@
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
if (getParent() != null) {
super.onParentChanged(newParent, oldParent, () -> {
- mColorBackgroundLayer = makeChildSurface(null)
- .setColorLayer()
- .setName("colorBackgroundLayer")
- .setCallsite("TaskDisplayArea.onParentChanged")
- .build();
mAppAnimationLayer = makeChildSurface(null)
.setName("animationLayer")
.setCallsite("TaskDisplayArea.onParentChanged")
@@ -1011,13 +1013,11 @@
} else {
super.onParentChanged(newParent, oldParent);
mWmService.mTransactionFactory.get()
- .remove(mColorBackgroundLayer)
.remove(mAppAnimationLayer)
.remove(mBoostedAppAnimationLayer)
.remove(mHomeAppAnimationLayer)
.remove(mSplitScreenDividerAnchor)
.apply();
- mColorBackgroundLayer = null;
mAppAnimationLayer = null;
mBoostedAppAnimationLayer = null;
mHomeAppAnimationLayer = null;
@@ -1025,35 +1025,29 @@
}
}
- void setBackgroundColor(@ColorInt int color) {
- if (mColorBackgroundLayer == null) {
- return;
- }
-
- float r = ((color >> 16) & 0xff) / 255.0f;
- float g = ((color >> 8) & 0xff) / 255.0f;
- float b = ((color >> 0) & 0xff) / 255.0f;
- float a = ((color >> 24) & 0xff) / 255.0f;
-
+ void setBackgroundColor(@ColorInt int colorInt) {
+ mBackgroundColor = colorInt;
+ Color color = Color.valueOf(colorInt);
mColorLayerCounter++;
- getPendingTransaction().setLayer(mColorBackgroundLayer, MIN_VALUE)
- .setColor(mColorBackgroundLayer, new float[]{r, g, b})
- .setAlpha(mColorBackgroundLayer, a)
- .setWindowCrop(mColorBackgroundLayer, getSurfaceWidth(), getSurfaceHeight())
- .setPosition(mColorBackgroundLayer, 0, 0)
- .show(mColorBackgroundLayer);
-
- scheduleAnimation();
+ // Only apply the background color if the TDA is actually attached and has a valid surface
+ // to set the background color on. We still want to keep track of the background color state
+ // even if we are not showing it for when/if the TDA is reattached and gets a valid surface
+ if (mSurfaceControl != null) {
+ getPendingTransaction()
+ .setColor(mSurfaceControl,
+ new float[]{color.red(), color.green(), color.blue()});
+ scheduleAnimation();
+ }
}
void clearBackgroundColor() {
mColorLayerCounter--;
// Only clear the color layer if we have received the same amounts of clear as set
- // requests.
- if (mColorLayerCounter == 0) {
- getPendingTransaction().hide(mColorBackgroundLayer);
+ // requests and TDA has a non null surface control (i.e. is attached)
+ if (mColorLayerCounter == 0 && mSurfaceControl != null) {
+ getPendingTransaction().unsetColor(mSurfaceControl);
scheduleAnimation();
}
}
@@ -1061,12 +1055,16 @@
@Override
void migrateToNewSurfaceControl(SurfaceControl.Transaction t) {
super.migrateToNewSurfaceControl(t);
+
+ if (mColorLayerCounter > 0) {
+ setBackgroundColor(mBackgroundColor);
+ }
+
if (mAppAnimationLayer == null) {
return;
}
// As TaskDisplayArea is getting a new surface, reparent and reorder the child surfaces.
- t.reparent(mColorBackgroundLayer, mSurfaceControl);
t.reparent(mAppAnimationLayer, mSurfaceControl);
t.reparent(mBoostedAppAnimationLayer, mSurfaceControl);
t.reparent(mHomeAppAnimationLayer, mSurfaceControl);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index a518222..71893f4 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -288,7 +288,7 @@
}
final ActivityRecord activity = result.first;
final WindowState mainWindow = result.second;
- final Rect contentInsets = getSystemBarInsets(task.getBounds(),
+ final Rect contentInsets = getSystemBarInsets(mainWindow.getFrame(),
mainWindow.getInsetsStateWithVisibilityOverride());
InsetUtils.addInsets(contentInsets, activity.getLetterboxInsets());
@@ -554,7 +554,7 @@
final LayoutParams attrs = mainWindow.getAttrs();
final Rect taskBounds = task.getBounds();
final InsetsState insetsState = mainWindow.getInsetsStateWithVisibilityOverride();
- final Rect systemBarInsets = getSystemBarInsets(taskBounds, insetsState);
+ final Rect systemBarInsets = getSystemBarInsets(mainWindow.getFrame(), insetsState);
final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
attrs.privateFlags, attrs.insetsFlags.appearance, task.getTaskDescription(),
mHighResTaskSnapshotScale, insetsState);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e48b5e1..e755b9e 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -47,7 +47,6 @@
"com_android_server_lights_LightsService.cpp",
"com_android_server_location_GnssLocationProvider.cpp",
"com_android_server_locksettings_SyntheticPasswordManager.cpp",
- "com_android_server_net_NetworkStatsService.cpp",
"com_android_server_power_PowerManagerService.cpp",
"com_android_server_powerstats_PowerStatsService.cpp",
"com_android_server_hint_HintManagerService.cpp",
@@ -73,7 +72,6 @@
"com_android_server_sensor_SensorService.cpp",
"onload.cpp",
":lib_cachedAppOptimizer_native",
- ":lib_networkStatsFactory_native",
],
include_dirs: [
@@ -85,7 +83,6 @@
header_libs: [
"bionic_libc_platform_headers",
- "bpf_connectivity_headers",
],
}
@@ -140,9 +137,6 @@
"libhidlbase",
"libutils",
"libhwui",
- "libbpf_android",
- "libnetdutils",
- "libnetworkstats",
"libpsi",
"libdataloader",
"libincfs",
@@ -205,13 +199,6 @@
}
filegroup {
- name: "lib_networkStatsFactory_native",
- srcs: [
- "com_android_server_net_NetworkStatsFactory.cpp",
- ],
-}
-
-filegroup {
name: "lib_cachedAppOptimizer_native",
srcs: [
"com_android_server_am_CachedAppOptimizer.cpp",
diff --git a/services/core/jni/BroadcastRadio/types.h b/services/core/jni/BroadcastRadio/types.h
index 910bb7c..4d286bf 100644
--- a/services/core/jni/BroadcastRadio/types.h
+++ b/services/core/jni/BroadcastRadio/types.h
@@ -30,13 +30,13 @@
// Keep in sync with STATUS_* constants from RadioManager.java.
enum class Status : jint {
OK = 0,
- ERROR = -0x80000000ll, // Integer.MIN_VALUE
+ ERROR = -0x80000000LL, // Integer.MIN_VALUE
PERMISSION_DENIED = -1, // -EPERM
- NO_INIT = -19, // -ENODEV
- BAD_VALUE = -22, // -EINVAL
- DEAD_OBJECT = -32, // -EPIPE
- INVALID_OPERATION = -38, // -ENOSYS
- TIMED_OUT = -110, // -ETIMEDOUT
+ NO_INIT = -19, // -ENODEV
+ BAD_VALUE = -22, // -EINVAL
+ DEAD_OBJECT = -32, // -EPIPE
+ INVALID_OPERATION = -38, // -ENOSYS
+ TIMED_OUT = -110, // -ETIMEDOUT
};
// Keep in sync with REGION_* constants from RadioManager.java.
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index ff61abc..9d3edd6 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -51,8 +51,6 @@
int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
int register_android_server_SyntheticPasswordManager(JNIEnv* env);
int register_android_hardware_display_DisplayViewport(JNIEnv* env);
-int register_android_server_net_NetworkStatsFactory(JNIEnv* env);
-int register_android_server_net_NetworkStatsService(JNIEnv* env);
int register_android_server_am_CachedAppOptimizer(JNIEnv* env);
int register_android_server_am_LowMemDetector(JNIEnv* env);
int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(JNIEnv* env);
@@ -107,8 +105,6 @@
register_android_server_SyntheticPasswordManager(env);
register_android_graphics_GraphicsStatsService(env);
register_android_hardware_display_DisplayViewport(env);
- register_android_server_net_NetworkStatsFactory(env);
- register_android_server_net_NetworkStatsService(env);
register_android_server_am_CachedAppOptimizer(env);
register_android_server_am_LowMemDetector(env);
register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl(env);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 710a9cf..4825f09 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -54,7 +54,6 @@
import android.net.ConnectivityManager;
import android.net.ConnectivityModuleConnector;
import android.net.NetworkStackClient;
-import android.net.TrafficStats;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
@@ -141,7 +140,6 @@
import com.android.server.media.metrics.MediaMetricsManagerService;
import com.android.server.media.projection.MediaProjectionManagerService;
import com.android.server.net.NetworkPolicyManagerService;
-import com.android.server.net.NetworkStatsService;
import com.android.server.net.watchlist.NetworkWatchlistService;
import com.android.server.notification.NotificationManagerService;
import com.android.server.oemlock.OemLockService;
@@ -379,6 +377,8 @@
"com.android.server.media.MediaResourceMonitorService";
private static final String CONNECTIVITY_SERVICE_INITIALIZER_CLASS =
"com.android.server.ConnectivityServiceInitializer";
+ private static final String NETWORK_STATS_SERVICE_INITIALIZER_CLASS =
+ "com.android.server.NetworkStatsServiceInitializer";
private static final String IP_CONNECTIVITY_METRICS_CLASS =
"com.android.server.connectivity.IpConnectivityMetrics";
private static final String MEDIA_COMMUNICATION_SERVICE_CLASS =
@@ -1334,10 +1334,8 @@
DynamicSystemService dynamicSystem = null;
IStorageManager storageManager = null;
NetworkManagementService networkManagement = null;
- IpSecService ipSecService = null;
VpnManagerService vpnManager = null;
VcnManagementService vcnManagement = null;
- NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
WindowManagerService wm = null;
SerialService serial = null;
@@ -1806,16 +1804,6 @@
}
t.traceEnd();
-
- t.traceBegin("StartIpSecService");
- try {
- ipSecService = IpSecService.create(context);
- ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService);
- } catch (Throwable e) {
- reportWtf("starting IpSec Service", e);
- }
- t.traceEnd();
-
t.traceBegin("StartFontManagerService");
mSystemServiceManager.startService(new FontManagerService.Lifecycle(context, safeMode));
t.traceEnd();
@@ -1836,13 +1824,10 @@
t.traceEnd();
t.traceBegin("StartNetworkStatsService");
- try {
- networkStats = NetworkStatsService.create(context);
- ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
- TrafficStats.init(context);
- } catch (Throwable e) {
- reportWtf("starting NetworkStats Service", e);
- }
+ // This has to be called before NetworkPolicyManager because NetworkPolicyManager
+ // needs to take NetworkStatsService to initialize.
+ mSystemServiceManager.startServiceFromJar(NETWORK_STATS_SERVICE_INITIALIZER_CLASS,
+ CONNECTIVITY_SERVICE_APEX_PATH);
t.traceEnd();
t.traceBegin("StartNetworkPolicyManagerService");
@@ -2659,7 +2644,6 @@
// These are needed to propagate to the runnable below.
final NetworkManagementService networkManagementF = networkManagement;
- final NetworkStatsService networkStatsF = networkStats;
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
final CountryDetectorService countryDetectorF = countryDetector;
final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
@@ -2667,7 +2651,6 @@
final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
final MediaRouterService mediaRouterF = mediaRouter;
final MmsServiceBroker mmsServiceF = mmsService;
- final IpSecService ipSecServiceF = ipSecService;
final VpnManagerService vpnManagerF = vpnManager;
final VcnManagementService vcnManagementF = vcnManagement;
final WindowManagerService windowManagerF = wm;
@@ -2757,24 +2740,6 @@
.networkScoreAndNetworkManagementServiceReady();
}
t.traceEnd();
- t.traceBegin("MakeIpSecServiceReady");
- try {
- if (ipSecServiceF != null) {
- ipSecServiceF.systemReady();
- }
- } catch (Throwable e) {
- reportWtf("making IpSec Service ready", e);
- }
- t.traceEnd();
- t.traceBegin("MakeNetworkStatsServiceReady");
- try {
- if (networkStatsF != null) {
- networkStatsF.systemReady();
- }
- } catch (Throwable e) {
- reportWtf("making Network Stats Service ready", e);
- }
- t.traceEnd();
t.traceBegin("MakeConnectivityServiceReady");
try {
if (connectivityF != null) {
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 62a16f7..c5f990d 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 @@
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 @@
}
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 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 @@
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/proguard.flags b/services/proguard.flags
index 5d01d3e..425da6c 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -1,21 +1,112 @@
-# TODO(b/196084106): Refine and optimize this configuration. Note that this
+# TODO(b/210510433): Refine and optimize this configuration. Note that this
# configuration is only used when `SOONG_CONFIG_ANDROID_SYSTEM_OPTIMIZE_JAVA=true`.
--keep,allowoptimization,allowaccessmodification class ** {
- !synthetic *;
-}
-# Various classes subclassed in ethernet-service (avoid marking final).
--keep public class android.net.** { *; }
-
-# Referenced via CarServiceHelperService in car-frameworks-service (avoid removing).
--keep public class com.android.server.utils.Slogf { *; }
+# Preserve line number information for debugging stack traces.
+-keepattributes SourceFile,LineNumberTable
# Allows making private and protected methods/fields public as part of
# optimization. This enables inlining of trivial getter/setter methods.
-allowaccessmodification
-# Disallow accessmodification for soundtrigger classes. Logging via reflective
-# public member traversal can cause infinite loops. See b/210901706.
--keep,allowoptimization class com.android.server.soundtrigger_middleware.** {
- !synthetic *;
+# Process entrypoint
+-keep class com.android.server.SystemServer {
+ public static void main(java.lang.String[]);
}
+
+# APIs referenced by dependent JAR files and modules
+-keep @interface android.annotation.SystemApi
+-keep @android.annotation.SystemApi class * {
+ public protected *;
+}
+-keepclasseswithmembers class * {
+ @android.annotation.SystemApi *;
+}
+
+# Derivatives of SystemService and other services created via reflection
+-keep,allowoptimization,allowaccessmodification class * extends com.android.server.SystemService {
+ public <methods>;
+}
+-keep,allowoptimization,allowaccessmodification class * extends com.android.server.devicepolicy.BaseIDevicePolicyManager {
+ public <init>(...);
+}
+-keep,allowoptimization,allowaccessmodification class com.android.server.wallpaper.WallpaperManagerService {
+ public <init>(...);
+}
+
+# Binder interfaces
+-keep,allowoptimization,allowaccessmodification class * extends android.os.IInterface
+-keep,allowoptimization,allowaccessmodification class * extends android.os.IHwInterface
+
+# Global entities normally kept through explicit Manifest entries
+# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/AndroidManifest.xml,
+# by including that manifest with the library rule that triggers optimization.
+-keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.app.Activity
+-keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.app.Service
+-keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.app.backup.BackupAgent
+-keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.content.BroadcastReceiver
+-keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.content.ContentProvider
+-keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.preference.Preference
+-keep,allowoptimization,allowaccessmodification class com.android.server.** extends android.view.View {
+ public <init>(...);
+}
+
+# Various classes subclassed in or referenced via JNI in ethernet-service
+-keep public class android.net.** { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.net.module.util.* { *; }
+-keep,allowoptimization,allowaccessmodification public class com.android.server.net.IpConfigStore { *; }
+-keep,allowoptimization,allowaccessmodification public class com.android.server.net.BaseNetworkObserver { *; }
+
+# Referenced via CarServiceHelperService in car-frameworks-service (avoid removing)
+-keep public class com.android.server.utils.Slogf { *; }
+
+# Notification extractors
+# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
+-keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
+
+# JNI keep rules
+# TODO(b/210510433): Revisit and fix with @Keep, or consider auto-generating from
+# frameworks/base/services/core/jni/onload.cpp.
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.BroadcastRadioService { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.Convert { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.Tuner { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.broadcastradio.hal1.TunerCallback { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.location.gnss.GnssConfiguration$HalInterfaceVersion { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.location.gnss.GnssPowerStats { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.location.gnss.hal.GnssNative { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.pm.PackageManagerShellCommandDataLoader { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.sensors.SensorManagerInternal$ProximityActiveListener { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.sensors.SensorService { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.soundtrigger_middleware.SoundTriggerMiddlewareImpl$AudioSessionProvider$AudioSession { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.soundtrigger_middleware.ExternalCaptureStateTracker { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.storage.AppFuseBridge { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.tv.TvInputHal { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbAlsaJackDetector { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbMidiDevice { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorController$OnVibrationCompleteListener { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.vibrator.VibratorManagerService$OnSyncedVibrationCompleteListener { *; }
+-keepclasseswithmembers,allowoptimization,allowaccessmodification class com.android.server.** {
+ *** *FromNative(...);
+}
+-keep,allowoptimization,allowaccessmodification class com.android.server.input.InputManagerService {
+ <methods>;
+}
+-keep,allowoptimization,allowaccessmodification class com.android.server.usb.UsbHostManager {
+ *** usbDeviceRemoved(...);
+ *** usbDeviceAdded(...);
+}
+-keep,allowoptimization,allowaccessmodification class **.*NativeWrapper* { *; }
+
+# Miscellaneous reflection keep rules
+# TODO(b/210510433): Revisit and fix with @Keep.
+-keep,allowoptimization,allowaccessmodification class com.android.server.usage.AppStandbyController {
+ public <init>(...);
+}
+-keep,allowoptimization,allowaccessmodification class android.hardware.usb.gadget.** { *; }
+
+# Needed when optimizations enabled
+# TODO(b/210510433): Revisit and fix with @Keep.
+-keep,allowoptimization,allowaccessmodification class com.android.server.SystemService { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.SystemService$TargetUser { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.server.usage.StorageStatsManagerLocal { *; }
+-keep,allowoptimization,allowaccessmodification class com.android.internal.util.** { *; }
+-keep,allowoptimization,allowaccessmodification class android.os.** { *; }
diff --git a/services/tests/servicestests/src/com/android/server/BootReceiverTest.java b/services/tests/servicestests/src/com/android/server/BootReceiverTest.java
deleted file mode 100644
index 489e2f7..0000000
--- a/services/tests/servicestests/src/com/android/server/BootReceiverTest.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.test.AndroidTestCase;
-
-/**
- * Tests for {@link com.android.server.BootReceiver}
- */
-public class BootReceiverTest extends AndroidTestCase {
- public void testLogLinePotentiallySensitive() throws Exception {
- /*
- * Strings to be dropped from the log as potentially sensitive: register dumps, process
- * names, hardware info.
- */
- final String[] becomeNull = {
- "CPU: 4 PID: 120 Comm: kunit_try_catch Tainted: G W 5.8.0-rc6+ #7",
- "Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1 04/01/2014",
- "[ 0.083207] RSP: 0000:ffffffff8fe07ca8 EFLAGS: 00010046 ORIG_RAX: 0000000000000000",
- "[ 0.084709] RAX: 0000000000000000 RBX: ffffffffff240000 RCX: ffffffff815fcf01",
- "[ 0.086109] RDX: dffffc0000000000 RSI: 0000000000000001 RDI: ffffffffff240004",
- "[ 0.087509] RBP: ffffffff8fe07d60 R08: fffffbfff1fc0f21 R09: fffffbfff1fc0f21",
- "[ 0.088911] R10: ffffffff8fe07907 R11: fffffbfff1fc0f20 R12: ffffffff8fe07d38",
- "R13: 0000000000000001 R14: 0000000000000001 R15: ffffffff8fe07e80",
- "x29: ffff00003ce07150 x28: ffff80001aa29cc0",
- "x1 : 0000000000000000 x0 : ffff00000f628000",
- };
-
- /* Strings to be left unchanged, including non-sensitive registers and parts of reports. */
- final String[] leftAsIs = {
- "FS: 0000000000000000(0000) GS:ffffffff92409000(0000) knlGS:0000000000000000",
- "[ 69.2366] [ T6006]c7 6006 =======================================================",
- "[ 69.245688] [ T6006] BUG: KFENCE: out-of-bounds in kfence_handle_page_fault",
- "[ 69.257816] [ T6006]c7 6006 Out-of-bounds access at 0xffffffca75c45000 ",
- "[ 69.273536] [ T6006]c7 6006 __do_kernel_fault+0xa8/0x11c",
- "pc : __mutex_lock+0x428/0x99c ",
- "sp : ffff00003ce07150",
- "Call trace:",
- "",
- };
-
- final String[][] stripped = {
- { "Detected corrupted memory at 0xffffffffb6797ff9 [ 0xac . . . . . . ]:",
- "Detected corrupted memory at 0xffffffffb6797ff9" },
- };
- for (int i = 0; i < becomeNull.length; i++) {
- assertEquals(BootReceiver.stripSensitiveData(becomeNull[i]), null);
- }
-
- for (int i = 0; i < leftAsIs.length; i++) {
- assertEquals(BootReceiver.stripSensitiveData(leftAsIs[i]), leftAsIs[i]);
- }
-
- for (int i = 0; i < stripped.length; i++) {
- assertEquals(BootReceiver.stripSensitiveData(stripped[i][0]), stripped[i][1]);
- }
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS
index 6a7d298..68994e6 100644
--- a/services/tests/servicestests/src/com/android/server/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/OWNERS
@@ -1,6 +1,6 @@
per-file *Alarm* = file:/apex/jobscheduler/OWNERS
per-file *AppOp* = file:/core/java/android/permission/OWNERS
-per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS
+per-file *Bluetooth* = file:platform/packages/modules/Bluetooth:master:/framework/java/android/bluetooth/OWNERS
per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS
per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS
per-file BatteryServiceTest.java = file:platform/hardware/interfaces:/health/aidl/OWNERS
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 9e1445c..bdea679 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.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 @@
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 @@
// 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 @@
// 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/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 01bd04c..77e49ad 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.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 @@
}
@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/locksettings/LockSettingsStrongAuthTest.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStrongAuthTest.java
index acb20ed..6de7fdd 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStrongAuthTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStrongAuthTest.java
@@ -229,8 +229,8 @@
}
private void verifyAlarm(long when, String tag, AlarmManager.OnAlarmListener alarm) {
- verify(mAlarmManager).set(
- eq(AlarmManager.ELAPSED_REALTIME),
+ verify(mAlarmManager).setExact(
+ eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
eq(when),
eq(tag),
eq(alarm),
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 94cf20f..1393d39 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -504,6 +504,7 @@
ArgumentCaptor.forClass(NetworkStatsManager.UsageCallback.class);
verify(mStatsManager, times(2))
.registerUsageCallback(any(), anyLong(), any(), usageObserver.capture());
+ // It doesn't matter which of the observers is returned here.
usageObserver.getValue().onThresholdReached(
new NetworkTemplate.Builder(MATCH_MOBILE).build());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 2bda120..f99f65e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -489,6 +489,20 @@
assertThat(e).hasMessageThat().contains("Failed to collect certificates from ");
}
+ @Test
+ public void testGetActivePackageNameForApexModuleName() throws Exception {
+ final String moduleName = "com.android.module_name";
+
+ ApexInfo[] apexInfo = createApexInfoForTestPkg(true, false);
+ apexInfo[0].moduleName = moduleName;
+ when(mApexService.getAllPackages()).thenReturn(apexInfo);
+ mApexManager.scanApexPackagesTraced(mPackageParser2,
+ ParallelPackageParser.makeExecutorService());
+
+ assertThat(mApexManager.getActivePackageNameForApexModuleName(moduleName))
+ .isEqualTo(TEST_APEX_PKG);
+ }
+
private ApexInfo[] createApexInfoForTestPkg(boolean isActive, boolean isFactory) {
File apexFile = extractResource(TEST_APEX_PKG, TEST_APEX_FILE_NAME);
ApexInfo apexInfo = new ApexInfo();
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
new file mode 100644
index 0000000..1d9ea4b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/ApexSharedLibraryUpdaterTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.parsing.library;
+
+import android.os.Build;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArrayMap;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.SystemConfig;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+
+/**
+ * Test for {@link ApexSharedLibraryUpdater}
+ */
+@Presubmit
+@SmallTest
+@RunWith(JUnit4.class)
+public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+ private final ArrayMap<String, SystemConfig.SharedLibraryEntry> mSharedLibraries =
+ new ArrayMap<>(8);
+
+ @Before
+ public void setUp() throws Exception {
+ installSharedLibraries();
+ }
+
+ private void installSharedLibraries() throws Exception {
+ mSharedLibraries.clear();
+ insertLibrary("foo", 0, 0);
+ insertLibrary("fooBcpSince30", 30, 0);
+ insertLibrary("fooBcpBefore30", 0, 30);
+ insertLibrary("fooFromFuture", Build.VERSION.SDK_INT + 2, 0);
+ }
+
+ private void insertLibrary(String libraryName, int onBootclasspathSince,
+ int onBootclasspathBefore) {
+ mSharedLibraries.put(libraryName, new SystemConfig.SharedLibraryEntry(
+ libraryName,
+ "foo.jar",
+ new String[0] /* dependencies */,
+ onBootclasspathSince,
+ onBootclasspathBefore
+ )
+ );
+ }
+
+ @Test
+ public void testRegularAppOnRPlus() {
+ // platform Q should have changes (tested below)
+
+ // these should have no changes
+ checkNoChanges(Build.VERSION_CODES.R);
+ checkNoChanges(Build.VERSION_CODES.S);
+ checkNoChanges(Build.VERSION_CODES.TIRAMISU);
+ checkNoChanges(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ }
+
+ private void checkNoChanges(int targetSdkVersion) {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(targetSdkVersion)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(targetSdkVersion)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpSince30Applied() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooBcpSince30")
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // note: target sdk is not what matters in this logic. It's the system SDK
+ // should be removed because on 30+ (R+) it is implicit
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpSince11kNotAppliedWithoutLibrary() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // note: target sdk is not what matters in this logic. It's the system SDK
+ // nothing should change because the implicit from is only from a future platform release
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpSince11kNotAppliedWithLibrary() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooFromFuture")
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooFromFuture")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // note: target sdk is not what matters in this logic. It's the system SDK
+ // nothing should change because the implicit from is only from a future platform release
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpBefore30NotApplied() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // should not be affected because it is still in the BCP in 30 / R
+ checkBackwardsCompatibility(before, after);
+ }
+
+ @Test
+ public void testBcpBefore30Applied() {
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .addUsesLibrary("fooBcpBefore30")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // should be present because this was in BCP in 29 / Q
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. All of this happening before the current
+ * SDK.
+ */
+ @Test
+ public void testBcpRemovedThenAddedPast() {
+ insertLibrary("fooBcpRemovedThenAdded", 30, 28);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.N)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.N)
+ .addUsesLibrary("fooBcpBefore30")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // the library is now in the BOOTCLASSPATH (for the second time) so it doesn't need to be
+ // listed
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. The first part happening before the
+ * current SDK and the second part after.
+ */
+ @Test
+ public void testBcpRemovedThenAddedMiddle_targetQ() {
+ insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.Q)
+ .addUsesLibrary("fooBcpRemovedThenAdded")
+ .addUsesLibrary("fooBcpBefore30")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // in this example, we are at the point where the library is not in the BOOTCLASSPATH.
+ // Because the app targets Q / 29 (when this library was in the BCP) then we need to add it
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. The first part happening before the
+ * current SDK and the second part after.
+ */
+ @Test
+ public void testBcpRemovedThenAddedMiddle_targetR() {
+ insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // in this example, we are at the point where the library is not in the BOOTCLASSPATH.
+ // Because the app targets R/30 (when this library was removed from the BCP) then we don't
+ //need to add it
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Test a library that was first removed from the BCP [to a mainline module] and later was
+ * moved back to the BCP via a mainline module update. The first part happening before the
+ * current SDK and the second part after.
+ */
+ @Test
+ public void testBcpRemovedThenAddedMiddle_targetR_usingLib() {
+ insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
+
+ ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooBcpRemovedThenAdded")
+ .hideAsParsed());
+
+ AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.R)
+ .addUsesLibrary("fooBcpRemovedThenAdded")
+ .hideAsParsed())
+ .hideAsFinal();
+
+ // in this example, we are at the point where the library is not in the BOOTCLASSPATH.
+ // Because the app wants to use the library, it needs to be present
+ checkBackwardsCompatibility(before, after);
+ }
+
+ private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
+ checkBackwardsCompatibility(before, after,
+ () -> new ApexSharedLibraryUpdater(mSharedLibraries));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
index 9768f17..5bcd0f6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
@@ -21,6 +21,8 @@
import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+import static com.google.common.truth.Truth.assertThat;
+
import android.content.pm.parsing.ParsingPackage;
import android.os.Build;
import android.platform.test.annotations.Presubmit;
@@ -182,6 +184,22 @@
checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal());
}
+ /**
+ * Ensures that ApexSharedLibraryUpdater is the last updater in the list of package updaters
+ * used by PackageBackwardCompatibility.
+ *
+ * This is required so mainline can add and remove libraries installed by the platform updaters.
+ */
+ @Test
+ public void testApexPackageUpdaterOrdering() {
+ PackageBackwardCompatibility instance =
+ (PackageBackwardCompatibility) PackageBackwardCompatibility.getInstance();
+ PackageSharedLibraryUpdater[] updaterArray = instance.getPackageUpdaters();
+
+ PackageSharedLibraryUpdater lastUpdater = updaterArray[updaterArray.length - 1];
+ assertThat(lastUpdater).isInstanceOf(ApexSharedLibraryUpdater.class);
+ }
+
private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
checkBackwardsCompatibility(before, after, PackageBackwardCompatibility::getInstance);
}
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
index b7199d4..150822b 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigNamedActorTest.kt
@@ -17,6 +17,7 @@
package com.android.server.systemconfig
import android.content.Context
+import android.util.Xml
import androidx.test.InstrumentationRegistry
import com.android.server.SystemConfig
import com.google.common.truth.Truth.assertThat
@@ -227,6 +228,7 @@
.writeText(this.trimIndent())
private fun assertPermissions() = SystemConfig(false).apply {
- readPermissions(tempFolder.root, 0)
+ val parser = Xml.newPullParser()
+ readPermissions(parser, tempFolder.root, 0)
}. let { assertThat(it.namedActors) }
}
diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
index 5eb21a5..bfdffc0 100644
--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
@@ -21,10 +21,12 @@
import static org.junit.Assert.assertEquals;
import static org.testng.Assert.expectThrows;
+import android.os.Build;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Xml;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -36,9 +38,12 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
@@ -59,12 +64,15 @@
private static final String LOG_TAG = "SystemConfigTest";
private SystemConfig mSysConfig;
+ private File mFooJar;
@Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
@Before
public void setUp() throws Exception {
mSysConfig = new SystemConfigTestClass();
+ mFooJar = createTempFile(
+ mTemporaryFolder.getRoot().getCanonicalFile(), "foo.jar", "JAR");
}
/**
@@ -76,6 +84,11 @@
}
}
+ private void readPermissions(File libraryDir, int permissionFlag) {
+ final XmlPullParser parser = Xml.newPullParser();
+ mSysConfig.readPermissions(parser, libraryDir, permissionFlag);
+ }
+
/**
* Tests that readPermissions works correctly for the tag: install-in-user-type
*/
@@ -126,16 +139,17 @@
new ArraySet<>(Arrays.asList("GUEST", "PROFILE")));
final File folder1 = createTempSubfolder("folder1");
- createTempFile(folder1, "permFile1.xml", contents1);
+ createTempFile(folder1, "permissionFile1.xml", contents1);
final File folder2 = createTempSubfolder("folder2");
- createTempFile(folder2, "permFile2.xml", contents2);
+ createTempFile(folder2, "permissionFile2.xml", contents2);
- // Also, make a third file, but with the name folder1/permFile2.xml, to prove no conflicts.
- createTempFile(folder1, "permFile2.xml", contents3);
+ // Also, make a third file, but with the name folder1/permissionFile2.xml, to prove no
+ // conflicts.
+ createTempFile(folder1, "permissionFile2.xml", contents3);
- mSysConfig.readPermissions(folder1, /* No permission needed anyway */ 0);
- mSysConfig.readPermissions(folder2, /* No permission needed anyway */ 0);
+ readPermissions(folder1, /* No permission needed anyway */ 0);
+ readPermissions(folder2, /* No permission needed anyway */ 0);
Map<String, Set<String>> actualWhite = mSysConfig.getAndClearPackageToUserTypeWhitelist();
Map<String, Set<String>> actualBlack = mSysConfig.getAndClearPackageToUserTypeBlacklist();
@@ -165,7 +179,7 @@
final File folder = createTempSubfolder("folder");
createTempFile(folder, "component-override.xml", contents);
- mSysConfig.readPermissions(folder, /* No permission needed anyway */ 0);
+ readPermissions(folder, /* No permission needed anyway */ 0);
final ArrayMap<String, Boolean> packageOneExpected = new ArrayMap<>();
packageOneExpected.put("com.android.package1.Full", true);
@@ -197,7 +211,7 @@
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getWhitelistedStagedInstallers())
.containsExactly("com.android.package1");
@@ -215,7 +229,7 @@
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getWhitelistedStagedInstallers())
.containsExactly("com.android.package1");
@@ -238,7 +252,7 @@
IllegalStateException e = expectThrows(
IllegalStateException.class,
- () -> mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0));
+ () -> readPermissions(folder, /* Grant all permission flags */ ~0));
assertThat(e).hasMessageThat().contains("Multiple modules installers");
}
@@ -257,7 +271,7 @@
final File folder = createTempSubfolder("folder");
createTempFile(folder, "staged-installer-whitelist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
+ readPermissions(folder, /* Grant all but ALLOW_APP_CONFIGS flag */ ~0x08);
assertThat(mSysConfig.getWhitelistedStagedInstallers()).isEmpty();
}
@@ -277,7 +291,7 @@
final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getAllowedVendorApexes())
.containsExactly("com.android.apex1", "com.installer");
@@ -297,7 +311,7 @@
final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all permission flags */ ~0);
+ readPermissions(folder, /* Grant all permission flags */ ~0);
assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
}
@@ -317,11 +331,273 @@
final File folder = createTempSubfolder("folder");
createTempFile(folder, "vendor-apex-allowlist.xml", contents);
- mSysConfig.readPermissions(folder, /* Grant all but ALLOW_VENDOR_APEX flag */ ~0x400);
+ readPermissions(folder, /* Grant all but ALLOW_VENDOR_APEX flag */ ~0x400);
assertThat(mSysConfig.getAllowedVendorApexes()).isEmpty();
}
+ @Test
+ public void readApexPrivAppPermissions_addAllPermissions()
+ throws Exception {
+ final String contents =
+ "<privapp-permissions package=\"com.android.apk_in_apex\">"
+ + "<permission name=\"android.permission.FOO\"/>"
+ + "<deny-permission name=\"android.permission.BAR\"/>"
+ + "</privapp-permissions>";
+ File apexDir = createTempSubfolder("apex");
+ File permissionFile = createTempFile(
+ createTempSubfolder("apex/com.android.my_module/etc/permissions"),
+ "permissions.xml", contents);
+ XmlPullParser parser = readXmlUntilStartTag(permissionFile);
+
+ mSysConfig.readApexPrivAppPermissions(parser, permissionFile, apexDir.toPath());
+
+ assertThat(mSysConfig.getApexPrivAppPermissions("com.android.my_module",
+ "com.android.apk_in_apex"))
+ .containsExactly("android.permission.FOO");
+ assertThat(mSysConfig.getApexPrivAppDenyPermissions("com.android.my_module",
+ "com.android.apk_in_apex"))
+ .containsExactly("android.permission.BAR");
+ }
+
+ @Test
+ public void pruneVendorApexPrivappAllowlists_removeVendor()
+ throws Exception {
+ File apexDir = createTempSubfolder("apex");
+
+ // Read non-vendor apex permission allowlists
+ final String allowlistNonVendorContents =
+ "<privapp-permissions package=\"com.android.apk_in_non_vendor_apex\">"
+ + "<permission name=\"android.permission.FOO\"/>"
+ + "<deny-permission name=\"android.permission.BAR\"/>"
+ + "</privapp-permissions>";
+ File nonVendorPermDir =
+ createTempSubfolder("apex/com.android.non_vendor/etc/permissions");
+ File nonVendorPermissionFile =
+ createTempFile(nonVendorPermDir, "permissions.xml", allowlistNonVendorContents);
+ XmlPullParser nonVendorParser = readXmlUntilStartTag(nonVendorPermissionFile);
+ mSysConfig.readApexPrivAppPermissions(nonVendorParser, nonVendorPermissionFile,
+ apexDir.toPath());
+
+ // Read vendor apex permission allowlists
+ final String allowlistVendorContents =
+ "<privapp-permissions package=\"com.android.apk_in_vendor_apex\">"
+ + "<permission name=\"android.permission.BAZ\"/>"
+ + "<deny-permission name=\"android.permission.BAT\"/>"
+ + "</privapp-permissions>";
+ File vendorPermissionFile =
+ createTempFile(createTempSubfolder("apex/com.android.vendor/etc/permissions"),
+ "permissions.xml", allowlistNonVendorContents);
+ XmlPullParser vendorParser = readXmlUntilStartTag(vendorPermissionFile);
+ mSysConfig.readApexPrivAppPermissions(vendorParser, vendorPermissionFile,
+ apexDir.toPath());
+
+ // Read allowed vendor apex list
+ final String allowedVendorContents =
+ "<config>\n"
+ + " <allowed-vendor-apex package=\"com.android.vendor\" "
+ + "installerPackage=\"com.installer\" />\n"
+ + "</config>";
+ final File allowedVendorFolder = createTempSubfolder("folder");
+ createTempFile(allowedVendorFolder, "vendor-apex-allowlist.xml", allowedVendorContents);
+ readPermissions(allowedVendorFolder, /* Grant all permission flags */ ~0);
+
+ // Finally, prune non-vendor allowlists.
+ // There is no guarantee in which order the above reads will be done, however pruning
+ // will always happen last.
+ mSysConfig.pruneVendorApexPrivappAllowlists();
+
+ assertThat(mSysConfig.getApexPrivAppPermissions("com.android.non_vendor",
+ "com.android.apk_in_non_vendor_apex"))
+ .containsExactly("android.permission.FOO");
+ assertThat(mSysConfig.getApexPrivAppDenyPermissions("com.android.non_vendor",
+ "com.android.apk_in_non_vendor_apex"))
+ .containsExactly("android.permission.BAR");
+ assertThat(mSysConfig.getApexPrivAppPermissions("com.android.vendor",
+ "com.android.apk_in_vendor_apex"))
+ .isNull();
+ assertThat(mSysConfig.getApexPrivAppDenyPermissions("com.android.vendor",
+ "com.android.apk_in_vendor_apex"))
+ .isNull();
+ }
+
+ /**
+ * Tests that readPermissions works correctly for a library with on-bootclasspath-before
+ * and on-bootclasspath-since.
+ */
+ @Test
+ public void readPermissions_allowLibs_parsesSimpleLibrary() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " on-bootclasspath-before=\"10\"\n"
+ + " on-bootclasspath-since=\"20\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+ assertThat(entry.onBootclasspathBefore).isEqualTo(10);
+ assertThat(entry.onBootclasspathSince).isEqualTo(20);
+ }
+
+ /**
+ * Tests that readPermissions works correctly for a library using the new
+ * {@code apex-library} tag.
+ */
+ @Test
+ public void readPermissions_allowLibs_parsesUpdatableLibrary() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <apex-library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " on-bootclasspath-before=\"10\"\n"
+ + " on-bootclasspath-since=\"20\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+ assertThat(entry.onBootclasspathBefore).isEqualTo(10);
+ assertThat(entry.onBootclasspathSince).isEqualTo(20);
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code min-device-sdk} lower than the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsOldMinSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " min-device-sdk=\"30\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code min-device-sdk} equal to the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsCurrentMinSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " min-device-sdk=\"" + Build.VERSION.SDK_INT + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code min-device-sdk} greater than the current
+ * SDK results in the library being ignored.
+ */
+ @Test
+ public void readPermissions_allowLibs_ignoresMinSdkInFuture() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " min-device-sdk=\"" + (Build.VERSION.SDK_INT + 1) + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertThat(mSysConfig.getSharedLibraries()).isEmpty();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code max-device-sdk} less than the current
+ * SDK results in the library being ignored.
+ */
+ @Test
+ public void readPermissions_allowLibs_ignoredOldMaxSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " max-device-sdk=\"30\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertThat(mSysConfig.getSharedLibraries()).isEmpty();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code max-device-sdk} equal to the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsCurrentMaxSdk() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " max-device-sdk=\"" + Build.VERSION.SDK_INT + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ /**
+ * Tests that readPermissions for a library with {@code max-device-sdk} greater than the current
+ * SDK results in the library being added to the shared libraries.
+ */
+ @Test
+ public void readPermissions_allowLibs_allowsMaxSdkInFuture() throws IOException {
+ String contents =
+ "<permissions>\n"
+ + " <library \n"
+ + " name=\"foo\"\n"
+ + " file=\"" + mFooJar + "\"\n"
+ + " max-device-sdk=\"" + (Build.VERSION.SDK_INT + 1) + "\"\n"
+ + " />\n\n"
+ + " </permissions>";
+ parseSharedLibraries(contents);
+ assertFooIsOnlySharedLibrary();
+ }
+
+ private void parseSharedLibraries(String contents) throws IOException {
+ File folder = createTempSubfolder("permissions_folder");
+ createTempFile(folder, "permissions.xml", contents);
+ readPermissions(folder, /* permissionFlag = ALLOW_LIBS */ 0x02);
+ }
+
+ /**
+ * Create an {@link XmlPullParser} for {@param permissionFile} and begin parsing it until
+ * reaching the root tag.
+ */
+ private XmlPullParser readXmlUntilStartTag(File permissionFile)
+ throws IOException, XmlPullParserException {
+ FileReader permReader = new FileReader(permissionFile);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(permReader);
+ int type;
+ do {
+ type = parser.next();
+ } while (type != parser.START_TAG && type != parser.END_DOCUMENT);
+ if (type != parser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+ return parser;
+ }
+
/**
* Creates folderName/fileName in the mTemporaryFolder and fills it with the contents.
*
@@ -331,7 +607,7 @@
private File createTempSubfolder(String folderName)
throws IOException {
File folder = new File(mTemporaryFolder.getRoot(), folderName);
- folder.mkdir();
+ folder.mkdirs();
return folder;
}
@@ -341,7 +617,7 @@
* @param folder pre-existing subdirectory of mTemporaryFolder to put the file
* @param fileName name of the file (e.g. filename.xml) to create
* @param contents contents to write to the file
- * @return the folder containing the newly created file (not the file itself!)
+ * @return the newly created file
*/
private File createTempFile(File folder, String fileName, String contents)
throws IOException {
@@ -357,6 +633,13 @@
Log.d(LOG_TAG, input.nextLine());
}
- return folder;
+ return file;
+ }
+
+ private void assertFooIsOnlySharedLibrary() {
+ assertThat(mSysConfig.getSharedLibraries().size()).isEqualTo(1);
+ SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+ assertThat(entry.name).isEqualTo("foo");
+ assertThat(entry.filename).isEqualTo(mFooJar.toString());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 32fed3b..4519890 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -252,7 +252,7 @@
int slotIndex = 1234;
TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
return new TelephonyTimeSuggestion.Builder(slotIndex)
- .setUtcTime(timeValue)
+ .setUnixEpochTime(timeValue)
.build();
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 0d5b5a5..2d9903f 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -52,12 +52,12 @@
@RunWith(AndroidJUnit4.class)
public class TimeDetectorStrategyImplTest {
- private static final Instant TIME_LOWER_BOUND = createUtcTime(2009, 1, 1, 12, 0, 0);
+ private static final Instant TIME_LOWER_BOUND = createUnixEpochTime(2009, 1, 1, 12, 0, 0);
private static final TimestampedValue<Instant> ARBITRARY_CLOCK_INITIALIZATION_INFO =
new TimestampedValue<>(
123456789L /* realtimeClockMillis */,
- createUtcTime(2010, 5, 23, 12, 0, 0));
+ createUnixEpochTime(2010, 5, 23, 12, 0, 0));
// This is the traditional ordering for time detection on Android.
private static final @Origin int [] PROVIDERS_PRIORITY = { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
@@ -66,7 +66,7 @@
* An arbitrary time, very different from the {@link #ARBITRARY_CLOCK_INITIALIZATION_INFO}
* time. Can be used as the basis for time suggestions.
*/
- private static final Instant ARBITRARY_TEST_TIME = createUtcTime(2018, 1, 1, 12, 0, 0);
+ private static final Instant ARBITRARY_TEST_TIME = createUnixEpochTime(2018, 1, 1, 12, 0, 0);
private static final int ARBITRARY_SLOT_INDEX = 123456;
@@ -91,7 +91,7 @@
.simulateTelephonyTimeSuggestion(timeSuggestion);
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
mScript.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
}
@@ -128,7 +128,7 @@
mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis1 =
- mScript.calculateTimeInMillisForNow(timeSuggestion1.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion1.getUnixEpochTime());
mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
@@ -155,7 +155,7 @@
mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis3 =
- mScript.calculateTimeInMillisForNow(timeSuggestion3.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion3.getUnixEpochTime());
mScript.simulateTelephonyTimeSuggestion(timeSuggestion3)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis3)
@@ -182,8 +182,8 @@
mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
mScript.simulateTimePassing();
- long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(slotIndex2TimeSuggestion.getUtcTime());
+ long expectedSystemClockMillis = mScript.calculateTimeInMillisForNow(
+ slotIndex2TimeSuggestion.getUnixEpochTime());
mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
@@ -199,8 +199,8 @@
mScript.generateTelephonyTimeSuggestion(slotIndex1, slotIndex1Time);
mScript.simulateTimePassing();
- long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(slotIndex1TimeSuggestion.getUtcTime());
+ long expectedSystemClockMillis = mScript.calculateTimeInMillisForNow(
+ slotIndex1TimeSuggestion.getUnixEpochTime());
mScript.simulateTelephonyTimeSuggestion(slotIndex1TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
@@ -232,8 +232,8 @@
mScript.generateTelephonyTimeSuggestion(slotIndex2, slotIndex2Time);
mScript.simulateTimePassing();
- long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(slotIndex2TimeSuggestion.getUtcTime());
+ long expectedSystemClockMillis = mScript.calculateTimeInMillisForNow(
+ slotIndex2TimeSuggestion.getUnixEpochTime());
mScript.simulateTelephonyTimeSuggestion(slotIndex2TimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
@@ -267,26 +267,27 @@
TelephonyTimeSuggestion timeSuggestion1 =
mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
- TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+ TimestampedValue<Long> unixEpochTime1 = timeSuggestion1.getUnixEpochTime();
// Initialize the strategy / device with a time set from a telephony suggestion.
mScript.simulateTimePassing();
- long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(utcTime1);
+ long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(unixEpochTime1);
mScript.simulateTelephonyTimeSuggestion(timeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
- // The UTC time increment should be larger than the system clock update threshold so we
- // know it shouldn't be ignored for other reasons.
- long validUtcTimeMillis = utcTime1.getValue() + (2 * systemClockUpdateThreshold);
+ // The Unix epoch time increment should be larger than the system clock update threshold so
+ // we know it shouldn't be ignored for other reasons.
+ long validUnixEpochTimeMillis = unixEpochTime1.getValue()
+ + (2 * systemClockUpdateThreshold);
// Now supply a new signal that has an obviously bogus reference time : older than the last
// one.
- long referenceTimeBeforeLastSignalMillis = utcTime1.getReferenceTimeMillis() - 1;
- TimestampedValue<Long> utcTime2 = new TimestampedValue<>(
- referenceTimeBeforeLastSignalMillis, validUtcTimeMillis);
+ long referenceTimeBeforeLastSignalMillis = unixEpochTime1.getReferenceTimeMillis() - 1;
+ TimestampedValue<Long> unixEpochTime2 = new TimestampedValue<>(
+ referenceTimeBeforeLastSignalMillis, validUnixEpochTimeMillis);
TelephonyTimeSuggestion timeSuggestion2 =
- createTelephonyTimeSuggestion(slotIndex, utcTime2);
+ createTelephonyTimeSuggestion(slotIndex, unixEpochTime2);
mScript.simulateTelephonyTimeSuggestion(timeSuggestion2)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -294,22 +295,22 @@
// Now supply a new signal that has an obviously bogus reference time : substantially in the
// future.
long referenceTimeInFutureMillis =
- utcTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
- TimestampedValue<Long> utcTime3 = new TimestampedValue<>(
- referenceTimeInFutureMillis, validUtcTimeMillis);
+ unixEpochTime1.getReferenceTimeMillis() + Integer.MAX_VALUE + 1;
+ TimestampedValue<Long> unixEpochTime3 = new TimestampedValue<>(
+ referenceTimeInFutureMillis, validUnixEpochTimeMillis);
TelephonyTimeSuggestion timeSuggestion3 =
- createTelephonyTimeSuggestion(slotIndex, utcTime3);
+ createTelephonyTimeSuggestion(slotIndex, unixEpochTime3);
mScript.simulateTelephonyTimeSuggestion(timeSuggestion3)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
- // Just to prove validUtcTimeMillis is valid.
- long validReferenceTimeMillis = utcTime1.getReferenceTimeMillis() + 100;
- TimestampedValue<Long> utcTime4 = new TimestampedValue<>(
- validReferenceTimeMillis, validUtcTimeMillis);
- long expectedSystemClockMillis4 = mScript.calculateTimeInMillisForNow(utcTime4);
+ // Just to prove validUnixEpochTimeMillis is valid.
+ long validReferenceTimeMillis = unixEpochTime1.getReferenceTimeMillis() + 100;
+ TimestampedValue<Long> unixEpochTime4 = new TimestampedValue<>(
+ validReferenceTimeMillis, validUnixEpochTimeMillis);
+ long expectedSystemClockMillis4 = mScript.calculateTimeInMillisForNow(unixEpochTime4);
TelephonyTimeSuggestion timeSuggestion4 =
- createTelephonyTimeSuggestion(slotIndex, utcTime4);
+ createTelephonyTimeSuggestion(slotIndex, unixEpochTime4);
mScript.simulateTelephonyTimeSuggestion(timeSuggestion4)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion4);
@@ -344,7 +345,7 @@
Instant testTime = ARBITRARY_TEST_TIME;
TelephonyTimeSuggestion timeSuggestion1 =
mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
- TimestampedValue<Long> utcTime1 = timeSuggestion1.getUtcTime();
+ TimestampedValue<Long> unixEpochTime1 = timeSuggestion1.getUnixEpochTime();
// Simulate time passing.
mScript.simulateTimePassing(clockIncrementMillis);
@@ -358,7 +359,7 @@
// Simulate more time passing.
mScript.simulateTimePassing(clockIncrementMillis);
- long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(utcTime1);
+ long expectedSystemClockMillis1 = mScript.calculateTimeInMillisForNow(unixEpochTime1);
// Turn on auto time detection.
mScript.simulateAutoTimeDetectionToggle()
@@ -379,7 +380,7 @@
mScript.simulateTimePassing(clockIncrementMillis);
long expectedSystemClockMillis2 =
- mScript.calculateTimeInMillisForNow(timeSuggestion2.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion2.getUnixEpochTime());
// The new time, though valid, should not be set in the system clock because auto time is
// disabled.
@@ -406,7 +407,7 @@
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(telephonySuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(telephonySuggestion.getUnixEpochTime());
mScript.simulateTelephonyTimeSuggestion(telephonySuggestion)
.verifySystemClockWasSetAndResetCallTracking(
expectedSystemClockMillis /* expectedNetworkBroadcast */)
@@ -416,7 +417,7 @@
assertEquals(telephonySuggestion, mScript.peekBestTelephonySuggestion());
// Simulate time passing, long enough that telephonySuggestion is now too old.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS);
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS);
// Look inside and check what the strategy considers the current best telephony suggestion.
// It should still be the, it's just no longer used.
@@ -435,7 +436,7 @@
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -457,7 +458,7 @@
mScript.simulateTimePassing();
long expectedAutoClockMillis =
- mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
@@ -480,7 +481,7 @@
mScript.simulateTimePassing();
long expectedManualClockMillis =
- mScript.calculateTimeInMillisForNow(manualTimeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(manualTimeSuggestion.getUnixEpochTime());
mScript.simulateManualTimeSuggestion(manualTimeSuggestion, true /* expectedResult */)
.verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
@@ -492,7 +493,7 @@
mScript.simulateAutoTimeDetectionToggle();
expectedAutoClockMillis =
- mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
mScript.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
@@ -540,7 +541,7 @@
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
mScript.simulateNetworkTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -586,7 +587,7 @@
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
mScript.simulateGnssTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -617,7 +618,7 @@
mScript.simulateTimePassing();
long expectedSystemClockMillis =
- mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
mScript.simulateExternalTimeSuggestion(timeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -671,7 +672,8 @@
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(networkTimeSuggestion1.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(
+ networkTimeSuggestion1.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, null)
@@ -690,7 +692,8 @@
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(
+ telephonyTimeSuggestion.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
@@ -700,7 +703,7 @@
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use".
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now another network suggestion is made. Telephony suggestions are prioritized over
@@ -720,7 +723,7 @@
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to
// be used but networkTimeSuggestion2 is not.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
// NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
// suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
@@ -743,7 +746,7 @@
// Verify the latest network time now wins.
mScript.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(networkTimeSuggestion2.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(networkTimeSuggestion2.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
@@ -774,7 +777,8 @@
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateGnssTimeSuggestion(gnssTimeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(gnssTimeSuggestion1.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(
+ gnssTimeSuggestion1.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestNetworkSuggestion(null)
@@ -793,7 +797,8 @@
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(networkTimeSuggestion.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(
+ networkTimeSuggestion.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
@@ -803,7 +808,7 @@
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use".
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now another gnss suggestion is made. Network suggestions are prioritized over
@@ -823,7 +828,7 @@
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to
// be used but networkTimeSuggestion2 is not.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
// NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
// suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
@@ -846,7 +851,7 @@
// Verify the latest gnss time now wins.
mScript.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
@@ -877,7 +882,8 @@
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateExternalTimeSuggestion(externalTimeSuggestion1)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(externalTimeSuggestion1.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(
+ externalTimeSuggestion1.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestNetworkSuggestion(null)
@@ -896,7 +902,8 @@
mScript.simulateTimePassing(smallTimeIncrementMillis)
.simulateNetworkTimeSuggestion(networkTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(networkTimeSuggestion.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(
+ networkTimeSuggestion.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
@@ -906,7 +913,7 @@
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use".
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2)
.verifySystemClockWasNotSetAndResetCallTracking();
// Now another external suggestion is made. Network suggestions are prioritized over
@@ -926,7 +933,7 @@
// Simulate some significant time passing: half the time allowed before a time signal
// becomes "too old to use". This should mean that networkTimeSuggestion is now too old to
// be used but externalTimeSuggestion2 is not.
- mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS / 2);
// NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
// suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
@@ -949,7 +956,7 @@
// Verify the latest external time now wins.
mScript.verifySystemClockWasSetAndResetCallTracking(
- mScript.calculateTimeInMillisForNow(externalTimeSuggestion2.getUtcTime()));
+ mScript.calculateTimeInMillisForNow(externalTimeSuggestion2.getUnixEpochTime()));
// Check internal state.
mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
@@ -1438,11 +1445,11 @@
* reference time.
*/
ManualTimeSuggestion generateManualTimeSuggestion(Instant suggestedTime) {
- TimestampedValue<Long> utcTime =
+ TimestampedValue<Long> unixEpochTime =
new TimestampedValue<>(
mFakeEnvironment.peekElapsedRealtimeMillis(),
suggestedTime.toEpochMilli());
- return new ManualTimeSuggestion(utcTime);
+ return new ManualTimeSuggestion(unixEpochTime);
}
/**
@@ -1472,11 +1479,11 @@
* reference time.
*/
NetworkTimeSuggestion generateNetworkTimeSuggestion(Instant suggestedTime) {
- TimestampedValue<Long> utcTime =
+ TimestampedValue<Long> unixEpochTime =
new TimestampedValue<>(
mFakeEnvironment.peekElapsedRealtimeMillis(),
suggestedTime.toEpochMilli());
- return new NetworkTimeSuggestion(utcTime);
+ return new NetworkTimeSuggestion(unixEpochTime);
}
/**
@@ -1484,11 +1491,11 @@
* reference time.
*/
GnssTimeSuggestion generateGnssTimeSuggestion(Instant suggestedTime) {
- TimestampedValue<Long> utcTime =
+ TimestampedValue<Long> unixEpochTime =
new TimestampedValue<>(
mFakeEnvironment.peekElapsedRealtimeMillis(),
suggestedTime.toEpochMilli());
- return new GnssTimeSuggestion(utcTime);
+ return new GnssTimeSuggestion(unixEpochTime);
}
/**
@@ -1504,19 +1511,19 @@
* Calculates what the supplied time would be when adjusted for the movement of the fake
* elapsed realtime clock.
*/
- long calculateTimeInMillisForNow(TimestampedValue<Long> utcTime) {
- return TimeDetectorStrategy.getTimeAt(utcTime, peekElapsedRealtimeMillis());
+ long calculateTimeInMillisForNow(TimestampedValue<Long> unixEpochTime) {
+ return TimeDetectorStrategy.getTimeAt(unixEpochTime, peekElapsedRealtimeMillis());
}
}
private static TelephonyTimeSuggestion createTelephonyTimeSuggestion(int slotIndex,
- TimestampedValue<Long> utcTime) {
+ TimestampedValue<Long> unixEpochTime) {
return new TelephonyTimeSuggestion.Builder(slotIndex)
- .setUtcTime(utcTime)
+ .setUnixEpochTime(unixEpochTime)
.build();
}
- private static Instant createUtcTime(int year, int monthInYear, int day, int hourOfDay,
+ private static Instant createUnixEpochTime(int year, int monthInYear, int day, int hourOfDay,
int minute, int second) {
return LocalDateTime.of(year, monthInYear, day, hourOfDay, minute, second)
.toInstant(ZoneOffset.UTC);
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 6f04f17..29fa2d3 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_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.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 @@
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/services/translation/OWNERS b/services/translation/OWNERS
index a1e663a..440f9a8 100644
--- a/services/translation/OWNERS
+++ b/services/translation/OWNERS
@@ -1,8 +1,3 @@
# Bug component: 994311
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+include /core/java/android/view/translation/OWNERS
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 8cb0909..21f789f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -492,6 +492,7 @@
// current USB state
private boolean mHostConnected;
+ private boolean mUsbAccessoryConnected;
private boolean mSourcePower;
private boolean mSinkPower;
private boolean mConfigured;
@@ -961,10 +962,10 @@
break;
case MSG_UPDATE_HOST_STATE:
Iterator devices = (Iterator) msg.obj;
- boolean connected = (msg.arg1 == 1);
+ mUsbAccessoryConnected = (msg.arg1 == 1);
if (DEBUG) {
- Slog.i(TAG, "HOST_STATE connected:" + connected);
+ Slog.i(TAG, "HOST_STATE connected:" + mUsbAccessoryConnected);
}
mHideUsbNotification = false;
@@ -1218,7 +1219,7 @@
} else if (mSourcePower) {
titleRes = com.android.internal.R.string.usb_supplying_notification_title;
id = SystemMessage.NOTE_USB_SUPPLYING;
- } else if (mHostConnected && mSinkPower && mUsbCharging) {
+ } else if (mHostConnected && mSinkPower && (mUsbCharging || mUsbAccessoryConnected)) {
titleRes = com.android.internal.R.string.usb_charging_notification_title;
id = SystemMessage.NOTE_USB_CHARGING;
}
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 1252965..9a991a1 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 @@
}
}
+ /**
+ * 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/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 23cf511..e88106c 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -1,6 +1,8 @@
package android.telephony;
import android.annotation.IntDef;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
import android.telecom.Connection;
import android.telephony.data.ApnSetting;
@@ -664,4 +666,59 @@
TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE,
TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR})
public @interface ThermalMitigationResult {}
+
+ /**
+ * Per Android API guideline 8.15, annotation can't be public APIs. So duplicate
+ * android.net.NetworkCapabilities.NetCapability here. Must update here when new capabilities
+ * are added in {@link NetworkCapabilities}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
+ NetworkCapabilities.NET_CAPABILITY_MMS,
+ NetworkCapabilities.NET_CAPABILITY_SUPL,
+ NetworkCapabilities.NET_CAPABILITY_DUN,
+ NetworkCapabilities.NET_CAPABILITY_FOTA,
+ NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_CBS,
+ NetworkCapabilities.NET_CAPABILITY_WIFI_P2P,
+ NetworkCapabilities.NET_CAPABILITY_IA,
+ NetworkCapabilities.NET_CAPABILITY_RCS,
+ NetworkCapabilities.NET_CAPABILITY_XCAP,
+ NetworkCapabilities.NET_CAPABILITY_EIMS,
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED,
+ NetworkCapabilities.NET_CAPABILITY_INTERNET,
+ NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED,
+ NetworkCapabilities.NET_CAPABILITY_TRUSTED,
+ NetworkCapabilities.NET_CAPABILITY_NOT_VPN,
+ NetworkCapabilities.NET_CAPABILITY_VALIDATED,
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL,
+ NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
+ NetworkCapabilities.NET_CAPABILITY_FOREGROUND,
+ NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED,
+ NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED,
+ NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
+ NetworkCapabilities.NET_CAPABILITY_MCX,
+ NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY,
+ NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED,
+ NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
+ NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL,
+ NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED,
+ NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
+ NetworkCapabilities.NET_CAPABILITY_VSIM,
+ NetworkCapabilities.NET_CAPABILITY_BIP,
+ NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT,
+ })
+ public @interface NetCapability { }
+
+ /**
+ * Per Android API guideline 8.15, annotation can't be public APIs. So duplicate
+ * android.net.NetworkAgent.ValidationStatus here. Must update here when new validation status
+ * are added in {@link NetworkAgent}.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "VALIDATION_STATUS_" }, value = {
+ NetworkAgent.VALIDATION_STATUS_VALID,
+ NetworkAgent.VALIDATION_STATUS_NOT_VALID
+ })
+ public @interface ValidationStatus {}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 9a764a0..8f957fd 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -28,6 +28,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
+import android.net.NetworkCapabilities;
import android.net.ipsec.ike.SaProposal;
import android.os.Build;
import android.os.PersistableBundle;
@@ -168,7 +169,10 @@
/**
* 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 +353,12 @@
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 +868,12 @@
/**
* 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 +887,11 @@
* 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";
@@ -3705,7 +3724,7 @@
/**
* SMDP+ server address for downloading opportunistic eSIM profile.
* FQDN (Fully Qualified Domain Name) of the SM-DP+ (e.g., smdp.gsma.com) restricted to the
- * Alphanumeric mode character set defined in table 5 of ISO/IEC 18004 [15] excluding '$'.
+ * Alphanumeric mode character set defined in table 5 of ISO/IEC 18004 excluding '$'.
*/
public static final String KEY_SMDP_SERVER_ADDRESS_STRING =
"smdp_server_address_string";
@@ -3749,29 +3768,52 @@
"opportunistic_carrier_ids_int_array";
/**
- * Controls RSRP threshold at which OpportunisticNetworkService will decide whether
+ * Boolean configuration to control auto provisioning eSIM download in
+ * OpportunisticNetworkService using only WiFi or both WiFi/Data.
+ * True will download esim only via WiFi.
+ * False will use both WiFi and Data connection.
+ *
+ * @hide
+ */
+ public static final String KEY_OPPORTUNISTIC_ESIM_DOWNLOAD_VIA_WIFI_ONLY_BOOL =
+ "opportunistic_esim_download_via_wifi_only_bool";
+
+/**
+ * Controls RSRP threshold, in dBm, at which OpportunisticNetworkService will decide whether
* the opportunistic network is good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRsrp()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT =
"opportunistic_network_entry_threshold_rsrp_int";
/**
- * Controls RSSNR threshold at which OpportunisticNetworkService will decide whether
- * the opportunistic network is good enough for internet data.
+ * Controls RSSNR threshold, in dB, at which OpportunisticNetworkService will
+ * decide whether the opportunistic network is good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRssnr()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT =
"opportunistic_network_entry_threshold_rssnr_int";
/**
- * Controls RSRP threshold below which OpportunisticNetworkService will decide whether
+ * Controls RSRP threshold, in dBm, below which OpportunisticNetworkService will decide whether
* the opportunistic network available is not good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRsrp()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT =
"opportunistic_network_exit_threshold_rsrp_int";
/**
- * Controls RSSNR threshold below which OpportunisticNetworkService will decide whether
- * the opportunistic network available is not good enough for internet data.
+ * Controls RSSNR threshold, in dB, below which OpportunisticNetworkService will
+ * decide whether the opportunistic network available is not good enough for internet data.
+ *
+ * <p>The value of {@link CellSignalStrengthLte#getRssnr()} will be compared with this
+ * threshold.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT =
"opportunistic_network_exit_threshold_rssnr_int";
@@ -3855,101 +3897,248 @@
public static final String KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG =
"opportunistic_network_max_backoff_time_long";
- /**
- * Controls SS-RSRP threshold in dBm at which 5G opportunistic network will be considered good
- * enough for internet data.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT =
- "opportunistic_network_entry_threshold_ss_rsrp_int";
+ /** @hide */
+ public static class OpportunisticNetwork {
+ /**
+ * Prefix of all {@code OpportunisticNetwork.KEY_*} constants.
+ *
+ * @hide
+ */
+ public static final String PREFIX = "opportunistic.";
- /**
- * Controls SS-RSRQ threshold in dB at which 5G opportunistic network will be considered good
- * enough for internet data.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE =
- "opportunistic_network_entry_threshold_ss_rsrq_double";
+ /**
+ * Controls SS-RSRP threshold in dBm at which 5G opportunistic network will be considered
+ * good enough for internet data. Note other factors may be considered for the final
+ * decision.
+ *
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrp()} will be compared with this
+ * threshold.
+ *
+ * @hide
+ */
+ public static final String KEY_ENTRY_THRESHOLD_SS_RSRP_INT =
+ PREFIX + "entry_threshold_ss_rsrp_int";
- /**
- * Controls SS-RSRP threshold in dBm below which 5G opportunistic network available will not
- * be considered good enough for internet data.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT =
- "opportunistic_network_exit_threshold_ss_rsrp_int";
+ /**
+ * Similar to {@link #KEY_ENTRY_THRESHOLD_SS_RSRP_INT} but supports different
+ * thresholds for different 5G bands. For bands not specified here, the threshold
+ * will be {@link #KEY_ENTRY_THRESHOLD_SS_RSRP_INT}.
+ *
+ * <p>For each key-value in the bundle: the key is the band number in string, which
+ * shall be a decimal integer as defined in {@code NgranBands.BAND_*} constants;
+ * the value is the threshold in int.
+ *
+ * @hide
+ */
+ public static final String KEY_ENTRY_THRESHOLD_SS_RSRP_INT_BUNDLE =
+ PREFIX + "entry_threshold_ss_rsrp_int_bundle";
- /**
- * Controls SS-RSRQ threshold in dB below which 5G opportunistic network available will not
- * be considered good enough for internet data.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE =
- "opportunistic_network_exit_threshold_ss_rsrq_double";
+ /**
+ * Controls SS-RSRQ threshold in dB at which 5G opportunistic network will be considered
+ * good enough for internet data. Note other factors may be considered for the final
+ * decision.
+ *
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrq()} will be compared with this
+ * threshold.
+ *
+ * @hide
+ */
+ public static final String KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE =
+ PREFIX + "entry_threshold_ss_rsrq_double";
- /**
- * Controls back off time in milliseconds for switching back to
- * 5G opportunistic subscription. This time will be added to
- * {@link CarrierConfigManager#KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG} to
- * determine hysteresis time if there is ping pong situation
- * (determined by system app or 1st party app) between primary and 5G opportunistic
- * subscription. Ping ping situation is defined in
- * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG.
- * If ping pong situation continuous #KEY_OPPORTUNISTIC_5G_NETWORK_BACKOFF_TIME_LONG
- * will be added to previously determined hysteresis time.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG =
- "opportunistic_network_5g_backoff_time_long";
+ /**
+ * Similar to {@link #KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE} but supports different
+ * thresholds for different 5G bands. For bands not specified here, the threshold
+ * will be {@link #KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE}.
+ *
+ * <p>For each key-value in the bundle: the key is the band number in string, which
+ * shall be a decimal integer as defined in {@code NgranBands.BAND_*} constants;
+ * the value is the threshold in double.
+ *
+ * @hide
+ */
+ public static final String KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE =
+ PREFIX + "entry_threshold_ss_rsrq_double_bundle";
- /**
- * Controls the max back off time in milliseconds for switching back to
- * 5G opportunistic subscription.
- * This time will be the max hysteresis that can be determined irrespective of there is
- * continuous ping pong situation or not as described in
- * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG and
- * #KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG =
- "opportunistic_network_5g_max_backoff_time_long";
+ /**
+ * Controls SS-RSRP threshold in dBm below which 5G opportunistic network available will not
+ * be considered good enough for internet data. Note other factors may be considered
+ * for the final decision.
+ *
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrp()} will be compared with this
+ * threshold.
+ *
+ * @hide
+ */
+ public static final String KEY_EXIT_THRESHOLD_SS_RSRP_INT =
+ PREFIX + "exit_threshold_ss_rsrp_int";
- /**
- * Controls the ping pong determination of 5G opportunistic network.
- * If opportunistic network is determined as out of service or below
- * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT or
- * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_INT within
- * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG of switching to opportunistic network,
- * it will be determined as ping pong situation by system app or 1st party app.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG =
- "opportunistic_network_5g_ping_pong_time_long";
+ /**
+ * Similar to {@link #KEY_EXIT_THRESHOLD_SS_RSRP_INT} but supports different
+ * thresholds for different 5G bands. For bands not specified here, the threshold
+ * will be {@link #KEY_EXIT_THRESHOLD_SS_RSRP_INT}.
+ *
+ * <p>The syntax of its value is similar to
+ * {@link #KEY_ENTRY_THRESHOLD_SS_RSRP_INT_BUNDLE}.
+ *
+ * @hide
+ */
+ public static final String KEY_EXIT_THRESHOLD_SS_RSRP_INT_BUNDLE =
+ PREFIX + "exit_threshold_ss_rsrp_int_bundle";
- /**
- * Controls hysteresis time in milliseconds for which will be waited before switching
- * data to a 5G opportunistic network.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG =
- "opportunistic_network_5g_data_switch_hysteresis_time_long";
+ /**
+ * Controls SS-RSRQ threshold in dB below which 5G opportunistic network available will not
+ * be considered good enough for internet data. Note other factors may be considered
+ * for the final decision.
+ *
+ * <p>The value of {@link CellSignalStrengthNr#getSsRsrq()} will be compared with this
+ * threshold.
+ *
+ * @hide
+ */
+ public static final String KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE =
+ PREFIX + "exit_threshold_ss_rsrq_double";
- /**
- * Controls hysteresis time in milliseconds for which will be waited before switching from
- * 5G opportunistic network to primary network.
- *
- * @hide
- */
- public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG =
- "opportunistic_network_5g_data_switch_exit_hysteresis_time_long";
+ /**
+ * Similar to {@link #KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE} but supports different
+ * thresholds for different 5G bands. For bands not specified here, the threshold
+ * will be {@link #KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE}.
+ *
+ * <p>The syntax of its value is similar to
+ * {@link #KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE}.
+ *
+ * @hide
+ */
+ public static final String KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE =
+ PREFIX + "exit_threshold_ss_rsrq_double_bundle";
+
+ /**
+ * Controls hysteresis time in milliseconds for which will be waited before switching
+ * data to a 5G opportunistic network.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG =
+ PREFIX + "5g_data_switch_hysteresis_time_long";
+
+ /**
+ * Similar to {@link #KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG} but supports
+ * different values for different 5G bands. For bands not specified here, the threshold
+ * will be {@link #KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG}.
+ *
+ * <p>For each key-value in the bundle: the key is the band number in string, which
+ * shall be a decimal integer as defined in {@code NgranBands.BAND_*} constants;
+ * the value is the time in long.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG_BUNDLE =
+ PREFIX + "5g_data_switch_hysteresis_time_long_bundle";
+
+ /**
+ * Controls hysteresis time in milliseconds for which will be waited before switching from
+ * 5G opportunistic network to primary network.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG =
+ PREFIX + "5g_data_switch_exit_hysteresis_time_long";
+
+ /**
+ * Similar to {@link #KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG} but supports
+ * different values for different 5G bands. For bands not specified here, the threshold
+ * will be {@link #KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG}.
+ *
+ * <p>The syntax is similar to
+ * {@link KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG_BUNDLE}.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG_BUNDLE =
+ PREFIX + "5g_data_switch_exit_hysteresis_time_long_bundle";
+
+ /**
+ * Controls back off time in milliseconds for switching back to
+ * 5G opportunistic subscription. This time will be added to
+ * {@link #KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG} to
+ * determine hysteresis time if there is ping pong situation
+ * (determined by system app or 1st party app) between primary and 5G opportunistic
+ * subscription. Ping ping situation is defined in
+ * {@link #KEY_5G_PING_PONG_TIME_LONG}.
+ * If ping pong situation continuous {@link #KEY_5G_NETWORK_BACKOFF_TIME_LONG}
+ * will be added to previously determined hysteresis time.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_BACKOFF_TIME_LONG =
+ PREFIX + "5g_backoff_time_long";
+
+ /**
+ * Controls the max back off time in milliseconds for switching back to
+ * 5G opportunistic subscription.
+ * This time will be the max hysteresis that can be determined irrespective of there is
+ * continuous ping pong situation or not as described in
+ * {@link #KEY_5G_PING_PONG_TIME_LONG} and
+ * {@link #KEY_5G_BACKOFF_TIME_LONG}.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_MAX_BACKOFF_TIME_LONG =
+ PREFIX + "5g_max_backoff_time_long";
+
+ /**
+ * Controls the ping pong determination of 5G opportunistic network.
+ * If opportunistic network is determined as out of service or below
+ * {@link #KEY_EXIT_THRESHOLD_SS_RSRP_INT} or
+ * {@link #KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE} within
+ * {@link #KEY_5G_PING_PONG_TIME_LONG} of switching to opportunistic network,
+ * it will be determined as ping pong situation by system app or 1st party app.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_PING_PONG_TIME_LONG =
+ PREFIX + "5g_ping_pong_time_long";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ // Default value is -111 dBm for all bands.
+ sDefaults.putInt(KEY_ENTRY_THRESHOLD_SS_RSRP_INT, -111);
+ sDefaults.putPersistableBundle(KEY_ENTRY_THRESHOLD_SS_RSRP_INT_BUNDLE,
+ PersistableBundle.EMPTY);
+ // Default value is -18.5 dB for all bands.
+ sDefaults.putDouble(KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
+ sDefaults.putPersistableBundle(
+ KEY_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE,
+ PersistableBundle.EMPTY);
+ // Default value is -120 dBm for all bands.
+ sDefaults.putInt(KEY_EXIT_THRESHOLD_SS_RSRP_INT, -120);
+ sDefaults.putPersistableBundle(KEY_EXIT_THRESHOLD_SS_RSRP_INT_BUNDLE,
+ PersistableBundle.EMPTY);
+ // Default value is -18.5 dB for all bands.
+ sDefaults.putDouble(KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
+ sDefaults.putPersistableBundle(
+ KEY_EXIT_THRESHOLD_SS_RSRQ_DOUBLE_BUNDLE,
+ PersistableBundle.EMPTY);
+ // Default value is 2 seconds for all bands.
+ defaults.putLong(KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG, 2000);
+ defaults.putPersistableBundle(
+ KEY_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG_BUNDLE,
+ PersistableBundle.EMPTY);
+ // Default value is 2 seconds for all bands.
+ defaults.putLong(KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 2000);
+ defaults.putPersistableBundle(
+ KEY_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG_BUNDLE,
+ PersistableBundle.EMPTY);
+ // Default value is 10 seconds.
+ sDefaults.putLong(KEY_5G_BACKOFF_TIME_LONG, 10000);
+ // Default value is 60 seconds.
+ sDefaults.putLong(KEY_5G_MAX_BACKOFF_TIME_LONG, 60000);
+ // Default value is 60 seconds.
+ sDefaults.putLong(KEY_5G_PING_PONG_TIME_LONG, 60000);
+ return defaults;
+ }
+ }
+
/**
* Controls whether 4G opportunistic networks should be scanned for possible data switch.
*
@@ -4402,12 +4591,10 @@
"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 +4607,7 @@
* <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 +4632,15 @@
"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";
@@ -4596,6 +4779,15 @@
KEY_PREFIX + "enable_presence_group_subscribe_bool";
/**
+ * Flag indicating whether or not to use SIP URI when send a presence subscribe.
+ * When {@code true}, the device sets the To and Contact header to be SIP URI using
+ * the TelephonyManager#getIsimDomain" API.
+ * If {@code false}, the device uses a TEL URI.
+ */
+ public static final String KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL =
+ KEY_PREFIX + "use_sip_uri_for_presence_subscribe_bool";
+
+ /**
* An integer key associated with the period of time in seconds the non-rcs capability
* information of each contact is cached on the device.
* <p>
@@ -4637,6 +4829,134 @@
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_TYPE_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";
+
+ /**
+ * List of different RAT technologies on which Provisioning for Voice calling (IR.92)
+ * is supported.
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE
+ * <p>Possible values are,
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ */
+ public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY =
+ KEY_PREFIX + "capability_type_voice_int_array";
+
+ /**
+ * List of different RAT technologies on which Provisioning for Video Telephony (IR.94)
+ * is supported.
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO
+ * <p>Possible values are,
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ */
+ public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY =
+ KEY_PREFIX + "capability_type_video_int_array";
+
+ /**
+ * List of different RAT technologies on which Provisioning for XCAP over Ut for
+ * supplementary services. (IR.92) is supported.
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT
+ * <p>Possible values are,
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ */
+ public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY =
+ KEY_PREFIX + "capability_type_ut_int_array";
+
+ /**
+ * List of different RAT technologies on which Provisioning for SMS (IR.92) is supported.
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS
+ * <p>Possible values are,
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ */
+ public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY =
+ KEY_PREFIX + "capability_type_sms_int_array";
+
+ /**
+ * List of different RAT technologies on which Provisioning for Call Composer
+ * (section 2.4 of RCC.20) is supported.
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_CALL_COMPOSER
+ * <p>Possible values are,
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ */
+ public static final String KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY =
+ KEY_PREFIX + "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
+ * <p>Possible values are,
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ */
+ public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY =
+ KEY_PREFIX + "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
+ * <p>Possible values are,
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_LTE}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_IWLAN}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_CROSS_SIM}
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationImplBase.ImsRegistrationTech#REGISTRATION_TECH_NR}
+ */
+ public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY =
+ KEY_PREFIX + "capability_type_presence_uce_int_array";
+
private Ims() {}
private static PersistableBundle getDefaults() {
@@ -4649,6 +4969,7 @@
defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, false);
+ defaults.putBoolean(KEY_USE_SIP_URI_FOR_PRESENCE_SUBSCRIBE_BOOL, false);
defaults.putInt(KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT, 30 * 24 * 60 * 60);
defaults.putBoolean(KEY_RCS_REQUEST_FORBIDDEN_BY_SIP_489_BOOL, false);
defaults.putLong(KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG, 20 * 60 * 1000);
@@ -4673,6 +4994,17 @@
"+g.gsma.rcs.botversion=\"#=1,#=2\"",
"+g.gsma.rcs.cpimext"});
+ /**
+ * @see #KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
+ */
+ defaults.putPersistableBundle(
+ KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE, new PersistableBundle());
+ /**
+ * @see #KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
+ */
+ defaults.putPersistableBundle(
+ KEY_RCS_REQUIRES_PROVISIONING_BUNDLE, new PersistableBundle());
+
return defaults;
}
}
@@ -5133,6 +5465,53 @@
public static final String KEY_APN_PRIORITY_STRING_ARRAY = "apn_priority_string_array";
/**
+ * Network capability priority for determine the satisfy order in telephony. The priority is
+ * from the lowest 0 to the highest 100. The long-lived network shall have the lowest priority.
+ * This allows other short-lived requests like MMS requests to be established. Emergency request
+ * always has the highest priority.
+ *
+ * @hide
+ */
+ public static final String KEY_TELEPHONY_NETWORK_CAPABILITY_PRIORITIES_STRING_ARRAY =
+ "telephony_network_capability_priorities_string_array";
+
+ /**
+ * Defines the rules for data retry.
+ *
+ * The syntax of the retry rule:
+ * 1. Retry based on {@link NetworkCapabilities}. Note that only APN-type network capabilities
+ * are supported.
+ * "capabilities=[netCaps1|netCaps2|...], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
+ *
+ * 2. Retry based on {@link DataFailCause}
+ * "fail_causes=[cause1|cause2|cause3|..], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
+ *
+ * 3. Retry based on {@link NetworkCapabilities} and {@link DataFailCause}. Note that only
+ * APN-type network capabilities are supported.
+ * "capabilities=[netCaps1|netCaps2|...], fail_causes=[cause1|cause2|cause3|...],
+ * [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
+ *
+ * For example,
+ * "capabilities=eims, retry_interval=1000, maximum_retries=20" means if the attached
+ * network request is emergency, then retry data network setup every 1 second for up to 20
+ * times.
+ *
+ * "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|2254
+ * , maximum_retries=0" means for those fail causes, never retry with timers. Note that
+ * when environment changes, retry can still happen.
+ *
+ * "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
+ * "5000|10000|15000|20000|40000|60000|120000|240000|600000|1200000|1800000"
+ * "1800000, maximum_retries=20" means for those capabilities, retry happens in 2.5s, 3s, 5s,
+ * 10s, 15s, 20s, 40s, 1m, 2m, 4m, 10m, 20m, 30m, 30m, 30m, until reaching 20 retries.
+ *
+ * // TODO: remove KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS
+ * @hide
+ */
+ public static final String KEY_TELEPHONY_DATA_RETRY_RULES_STRING_ARRAY =
+ "telephony_data_retry_rules_string_array";
+
+ /**
* The patterns of missed incoming call sms. This is the regular expression used for
* matching the missed incoming call's date, time, and caller id. The pattern should match
* fields for at least month, day, hour, and minute. Year is optional although it is encouraged.
@@ -5421,6 +5800,7 @@
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);
@@ -5815,14 +6195,15 @@
sDefaults.putInt(KEY_ESIM_MAX_DOWNLOAD_RETRY_ATTEMPTS_INT, 5);
sDefaults.putInt(KEY_ESIM_DOWNLOAD_RETRY_BACKOFF_TIMER_SEC_INT, 60);
sDefaults.putIntArray(KEY_OPPORTUNISTIC_CARRIER_IDS_INT_ARRAY, new int[] {0});
+ sDefaults.putBoolean(KEY_OPPORTUNISTIC_ESIM_DOWNLOAD_VIA_WIFI_ONLY_BOOL, false);
/* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108);
/* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_MODERATE */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT, -118);
/* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_GOOD */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT, 45);
+ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSSNR_INT, 5);
/* Default value is minimum RSSNR level needed for SIGNAL_STRENGTH_MODERATE */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT, 10);
+ sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT, 1);
/* Default value is 1024 kbps */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT, 1024);
/* Default value is 10 seconds */
@@ -5831,6 +6212,7 @@
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
/* Default value is 3 seconds. */
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 3000);
+ sDefaults.putAll(OpportunisticNetwork.getDefaults());
sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true);
sDefaults.putBoolean(KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL, true);
/* Default value is 60 seconds. */
@@ -5839,24 +6221,6 @@
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000);
/* Default value is 60 seconds. */
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000);
- /* Default value is -111 dBm. */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT, -111);
- /* Default value is -18.5 dB. */
- sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
- /* Default value is -120 dBm. */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT, -120);
- /* Default value is -18.5 dB. */
- sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE, -18.5);
- /* Default value is 10 seconds. */
- sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG, 10000);
- /* Default value is 60 seconds. */
- sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG, 60000);
- /* Default value is 60 seconds. */
- sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG, 60000);
- /* Default value is 2 seconds. */
- sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG, 2000);
- /* Default value is 2 seconds. */
- sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 2000);
sDefaults.putBoolean(KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL, true);
sDefaults.putLong(KEY_TIME_TO_SWITCH_BACK_TO_PRIMARY_IF_OPPORTUNISTIC_OOS_LONG, 60000L);
sDefaults.putLong(
@@ -5915,6 +6279,24 @@
"enterprise:0", "default:1", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2",
"ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3"
});
+
+ // Do not modify the priority unless you know what you are doing. This will have significant
+ // impacts on the order of data network setup.
+ sDefaults.putStringArray(
+ KEY_TELEPHONY_NETWORK_CAPABILITY_PRIORITIES_STRING_ARRAY, new String[] {
+ "eims:90", "supl:80", "mms:70", "xcap:70", "cbs:50", "mcx:50", "fota:50",
+ "ims:40", "dun:30", "enterprise:20", "internet:20"
+ });
+ sDefaults.putStringArray(
+ KEY_TELEPHONY_DATA_RETRY_RULES_STRING_ARRAY, new String[] {
+ "capabilities=eims, retry_interval=1000, maximum_retries=20",
+ "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|"
+ + "2254, maximum_retries=0", // No retry for those causes
+ "capabilities=mms|supl|cbs, retry_interval=2000",
+ "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
+ + "5000|10000|15000|20000|40000|60000|120000|240000|"
+ + "600000|1200000|1800000, maximum_retries=20"
+ });
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 947dc01..5e90261 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -125,13 +125,13 @@
/**
* Construct a cell signal strength
*
- * @param rssi in dBm [-113,-51], UNKNOWN
- * @param rsrp in dBm [-140,-43], UNKNOWN
- * @param rsrq in dB [-34, 3], UNKNOWN
- * @param rssnr in dB [-20, +30], UNKNOWN
- * @param cqiTableIndex [1, 6], UNKNOWN
- * @param cqi [0, 15], UNKNOWN
- * @param timingAdvance [0, 1282], UNKNOWN
+ * @param rssi in dBm [-113,-51], {@link CellInfo#UNAVAILABLE}
+ * @param rsrp in dBm [-140,-43], {@link CellInfo#UNAVAILABLE}
+ * @param rsrq in dB [-34, 3], {@link CellInfo#UNAVAILABLE}
+ * @param rssnr in dB [-20, +30], {@link CellInfo#UNAVAILABLE}
+ * @param cqiTableIndex [1, 6], {@link CellInfo#UNAVAILABLE}
+ * @param cqi [0, 15], {@link CellInfo#UNAVAILABLE}
+ * @param timingAdvance [0, 1282], {@link CellInfo#UNAVAILABLE}
*
*/
/** @hide */
@@ -151,12 +151,12 @@
/**
* Construct a cell signal strength
*
- * @param rssi in dBm [-113,-51], UNKNOWN
- * @param rsrp in dBm [-140,-43], UNKNOWN
- * @param rsrq in dB [-34, 3], UNKNOWN
- * @param rssnr in dB [-20, +30], UNKNOWN
- * @param cqi [0, 15], UNKNOWN
- * @param timingAdvance [0, 1282], UNKNOWN
+ * @param rssi in dBm [-113,-51], {@link CellInfo#UNAVAILABLE}
+ * @param rsrp in dBm [-140,-43], {@link CellInfo#UNAVAILABLE}
+ * @param rsrq in dB [-34, 3], {@link CellInfo#UNAVAILABLE}
+ * @param rssnr in dB [-20, +30], {@link CellInfo#UNAVAILABLE}
+ * @param cqi [0, 15], {@link CellInfo#UNAVAILABLE}
+ * @param timingAdvance [0, 1282], {@link CellInfo#UNAVAILABLE}
*
*/
/** @hide */
@@ -403,10 +403,11 @@
}
/**
- * Get reference signal signal-to-noise ratio
+ * Get reference signal signal-to-noise ratio in dB
+ * Range: -20 dB to +30 dB.
*
* @return the RSSNR if available or
- * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
+ * {@link android.telephony.CellInfo#UNAVAILABLE} if unavailable.
*/
public int getRssnr() {
return mRssnr;
@@ -414,8 +415,10 @@
/**
* Get reference signal received power in dBm
+ * Range: -140 dBm to -43 dBm.
*
- * @return the RSRP of the measured cell.
+ * @return the RSRP of the measured cell or {@link CellInfo#UNAVAILABLE} if
+ * unavailable.
*/
public int getRsrp() {
return mRsrp;
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 88efe1f..56bf303 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1076,6 +1076,13 @@
*/
public static final int SERVICE_TEMPORARILY_UNAVAILABLE = 0x10009;
+ /**
+ * The request is not supported by the vendor.
+ *
+ * @hide
+ */
+ public static final int REQUEST_NOT_SUPPORTED = 0x1000A;
+
private static final Map<Integer, String> sFailCauseMap;
static {
sFailCauseMap = new HashMap<>();
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index fc76f99..6b9871c 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -160,6 +160,26 @@
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/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 846e6f3..9fd2ae4 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -767,6 +768,10 @@
*
* @return long name of operator, null if unregistered or unknown
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public String getOperatorAlphaLong() {
return mOperatorAlphaLong;
}
@@ -782,6 +787,10 @@
* @return long name of operator
* @hide
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
publicAlternatives = "Use {@link #getOperatorAlphaLong} instead.")
public String getVoiceOperatorAlphaLong() {
@@ -800,6 +809,10 @@
*
* @return short name of operator, null if unregistered or unknown
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public String getOperatorAlphaShort() {
return mOperatorAlphaShort;
}
@@ -815,6 +828,10 @@
* @return short name of operator, null if unregistered or unknown
* @hide
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
public String getVoiceOperatorAlphaShort() {
@@ -832,6 +849,10 @@
* @return short name of operator, null if unregistered or unknown
* @hide
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
publicAlternatives = "Use {@link #getOperatorAlphaShort} instead.")
public String getDataOperatorAlphaShort() {
@@ -853,6 +874,10 @@
* @return name of operator, null if unregistered or unknown
* @hide
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public String getOperatorAlpha() {
if (TextUtils.isEmpty(mOperatorAlphaLong)) {
return mOperatorAlphaShort;
@@ -878,6 +903,10 @@
* The country code can be decoded using
* {@link com.android.internal.telephony.MccTable#countryCodeForMcc(int)}.
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public String getOperatorNumeric() {
return mOperatorNumeric;
}
@@ -893,6 +922,10 @@
* @return numeric format of operator, null if unregistered or unknown
* @hide
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public String getVoiceOperatorNumeric() {
return mOperatorNumeric;
@@ -909,6 +942,10 @@
* @return numeric format of operator, null if unregistered or unknown
* @hide
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
publicAlternatives = "Use {@link #getOperatorNumeric} instead.")
public String getDataOperatorNumeric() {
@@ -1758,8 +1795,17 @@
/**
* Get the CDMA NID (Network Identification Number), a number uniquely identifying a network
* within a wireless system. (Defined in 3GPP2 C.S0023 3.4.8)
+ *
+ * <p>Require at least {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. Otherwise return
+ * {@link #UNKNOWN_ID}.
+ *
* @return The CDMA NID or {@link #UNKNOWN_ID} if not available.
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public int getCdmaNetworkId() {
return this.mNetworkId;
}
@@ -1767,8 +1813,17 @@
/**
* Get the CDMA SID (System Identification Number), a number uniquely identifying a wireless
* system. (Defined in 3GPP2 C.S0023 3.4.8)
+ *
+ * <p>Require at least {@link android.Manifest.permission#ACCESS_FINE_LOCATION} or
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}. Otherwise return
+ * {@link #UNKNOWN_ID}.
+ *
* @return The CDMA SID or {@link #UNKNOWN_ID} if not available.
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public int getCdmaSystemId() {
return this.mSystemId;
}
@@ -2069,6 +2124,8 @@
state.mOperatorAlphaLong = null;
state.mOperatorAlphaShort = null;
state.mOperatorNumeric = null;
+ state.mSystemId = UNKNOWN_ID;
+ state.mNetworkId = UNKNOWN_ID;
return state;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index aab6daa..390ffc7 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8765,7 +8765,8 @@
* @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 @@
/**
* 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 @@
* 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 @@
/**
* 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 @@
*
* {@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)) {
@@ -12127,12 +12111,15 @@
if (carriers == null || !SubscriptionManager.isValidPhoneId(slotIndex)) {
return -1;
}
- // Execute the method setCarrierRestrictionRules with an empty excluded list and
- // indicating priority for the allowed list.
+ // Execute the method setCarrierRestrictionRules with an empty excluded list.
+ // If the allowed list is empty, it means that all carriers are allowed (default allowed),
+ // otherwise it means that only specified carriers are allowed (default not allowed).
CarrierRestrictionRules carrierRestrictionRules = CarrierRestrictionRules.newBuilder()
.setAllowedCarriers(carriers)
.setDefaultCarrierRestriction(
- CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED)
+ carriers.isEmpty()
+ ? CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_ALLOWED
+ : CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED)
.build();
int result = setCarrierRestrictionRules(carrierRestrictionRules);
@@ -13026,127 +13013,88 @@
// 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 */
@@ -13201,12 +13149,11 @@
/**
* @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/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index d6dce25..8c02ffe 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -2158,8 +2158,7 @@
| TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX
| TYPE_XCAP | TYPE_VSIM | TYPE_BIP | TYPE_ENTERPRISE)) == 0
|| TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
- throw new IllegalArgumentException("mApName=" + mApnName + ", mEntryName="
- + mEntryName + ", mApnTypeBitmask=" + mApnTypeBitmask);
+ return null;
}
return new ApnSetting(this);
}
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 93903d2..c1d16a9 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -18,13 +18,16 @@
import static android.telephony.data.ApnSetting.ProtocolType;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.NetworkCapabilities;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.NetCapability;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.NetworkTypeBitMask;
import android.telephony.data.ApnSetting.AuthType;
@@ -66,7 +69,13 @@
private final @Nullable TrafficDescriptor mTrafficDescriptor;
- private final boolean mPreferred;
+ private boolean mPreferred;
+
+ /**
+ * The last timestamp of this data profile being used for data network setup. Never add this
+ * to {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ private @ElapsedRealtimeLong long mSetupTimestamp;
private DataProfile(@NonNull Builder builder) {
mApnSetting = builder.mApnSetting;
@@ -99,6 +108,7 @@
mApnSetting = source.readParcelable(ApnSetting.class.getClassLoader());
mTrafficDescriptor = source.readParcelable(TrafficDescriptor.class.getClassLoader());
mPreferred = source.readBoolean();
+ mSetupTimestamp = source.readLong();
}
/**
@@ -291,6 +301,16 @@
}
/**
+ * Set the preferred flag for the data profile.
+ *
+ * @param preferred {@code true} if this data profile is preferred for internet.
+ * @hide
+ */
+ public void setPreferred(boolean preferred) {
+ mPreferred = preferred;
+ }
+
+ /**
* @return {@code true} if this data profile was used to bring up the last default
* (i.e internet) data connection successfully, or the one chosen by the user in Settings'
* APN editor. For one carrier there can be only one profiled preferred.
@@ -315,6 +335,94 @@
return mTrafficDescriptor;
}
+ /**
+ * Check if this data profile can satisfy certain network capabilities
+ *
+ * @param networkCapabilities The network capabilities. Note that the non-APN-type capabilities
+ * will be ignored.
+ *
+ * @return {@code true} if this data profile can satisfy the given network capabilities.
+ * @hide
+ */
+ public boolean canSatisfy(@NonNull @NetCapability int[] networkCapabilities) {
+ if (mApnSetting != null) {
+ for (int netCap : networkCapabilities) {
+ if (!canSatisfy(netCap)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Check if this data profile can satisfy a certain network capability.
+ *
+ * @param networkCapability The network capability. Note that the non-APN-type capability
+ * will always be satisfied.
+ * @return {@code true} if this data profile can satisfy the given network capability.
+ * @hide
+ */
+ public boolean canSatisfy(@NetCapability int networkCapability) {
+ return mApnSetting != null && mApnSetting.canHandleType(
+ networkCapabilityToApnType(networkCapability));
+ }
+
+ /**
+ * Convert network capability into APN type.
+ *
+ * @param networkCapability Network capability.
+ * @return APN type.
+ * @hide
+ */
+ private static @ApnType int networkCapabilityToApnType(@NetCapability int networkCapability) {
+ switch (networkCapability) {
+ case NetworkCapabilities.NET_CAPABILITY_MMS:
+ return ApnSetting.TYPE_MMS;
+ case NetworkCapabilities.NET_CAPABILITY_SUPL:
+ return ApnSetting.TYPE_SUPL;
+ case NetworkCapabilities.NET_CAPABILITY_DUN:
+ return ApnSetting.TYPE_DUN;
+ case NetworkCapabilities.NET_CAPABILITY_FOTA:
+ return ApnSetting.TYPE_FOTA;
+ case NetworkCapabilities.NET_CAPABILITY_IMS:
+ return ApnSetting.TYPE_IMS;
+ case NetworkCapabilities.NET_CAPABILITY_CBS:
+ return ApnSetting.TYPE_CBS;
+ case NetworkCapabilities.NET_CAPABILITY_XCAP:
+ return ApnSetting.TYPE_XCAP;
+ case NetworkCapabilities.NET_CAPABILITY_EIMS:
+ return ApnSetting.TYPE_EMERGENCY;
+ case NetworkCapabilities.NET_CAPABILITY_INTERNET:
+ return ApnSetting.TYPE_DEFAULT;
+ case NetworkCapabilities.NET_CAPABILITY_MCX:
+ return ApnSetting.TYPE_MCX;
+ case NetworkCapabilities.NET_CAPABILITY_IA:
+ return ApnSetting.TYPE_IA;
+ default:
+ return ApnSetting.TYPE_NONE;
+ }
+ }
+
+ /**
+ * Set the timestamp of this data profile being used for data network setup.
+ *
+ * @hide
+ */
+ public void setLastSetupTimestamp(@ElapsedRealtimeLong long timestamp) {
+ mSetupTimestamp = timestamp;
+ }
+
+ /**
+ * @return the timestamp of this data profile being used for data network setup.
+ *
+ * @hide
+ */
+ public @ElapsedRealtimeLong long getLastSetupTimestamp() {
+ return mSetupTimestamp;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -323,8 +431,8 @@
@NonNull
@Override
public String toString() {
- return "DataProfile=" + mApnSetting + ", " + mTrafficDescriptor + ", preferred="
- + mPreferred;
+ return "[DataProfile=" + mApnSetting + ", " + mTrafficDescriptor + ", preferred="
+ + mPreferred + "]";
}
@Override
@@ -333,6 +441,7 @@
dest.writeParcelable(mApnSetting, flags);
dest.writeParcelable(mTrafficDescriptor, flags);
dest.writeBoolean(mPreferred);
+ dest.writeLong(mSetupTimestamp);
}
public static final @android.annotation.NonNull Parcelable.Creator<DataProfile> CREATOR =
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 051d6c5..13d8c7b 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -259,9 +259,10 @@
}
/**
- * 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 @@
/**
* 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 dfe5e6c9..d65286f 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -27,10 +27,12 @@
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 @@
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 @@
}
/** @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 @@
* 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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
@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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
@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 @@
@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 @@
*/
@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 @@
* 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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
*/
@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 @@
@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 9ab5aeb..be233b8 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.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 @@
// call ImsFeature#onFeatureRemoved.
private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
- private IImsServiceControllerListener mListener;
+ // 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 @@
}
@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 IImsRcsFeature createRcsFeature(int slotId) {
- return createRcsFeatureInternal(slotId);
+ 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, 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,18 +401,11 @@
return null;
}
- /**
- * @hide
- */
- @VisibleForTesting
- public SparseArray<ImsFeature> getFeatures(int slotId) {
- return mFeaturesBySlot.get(slotId);
- }
-
- private IImsMmTelFeature createMmTelFeatureInternal(int slotId) {
- MmTelFeature f = createMmTelFeature(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.");
@@ -307,9 +413,22 @@
}
}
- private IImsRcsFeature createRcsFeatureInternal(int slotId) {
- RcsFeature f = createRcsFeature(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, "createEmergencyOnlyMmTelFeatureInternal: null feature returned.");
+ return null;
+ }
+ }
+
+ 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 @@
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 @@
}
/**
+ * 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 @@
/**
* 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 @@
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 abc5606..5aef8a6 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -33,6 +33,7 @@
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 @@
* 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 @@
/**
* 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 @@
/**
* 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 @@
/**
* 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 @@
* <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 @@
/**
* Callback for IMS provisioning changes.
+ * @hide
*/
+ @SystemApi
public static class Callback {
private static class CallbackBinder extends IImsConfigCallback.Stub {
@@ -954,11 +965,105 @@
}
}
+ /**
+ * 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 @@
* @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 @@
return new ProvisioningManager(subId);
}
- private ProvisioningManager(int subId) {
+ /**@hide*/
+ //@SystemApi
+ public ProvisioningManager(int subId) {
mSubId = subId;
}
@@ -1114,6 +1223,12 @@
*
* 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 @@
* 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 @@
* 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 @@
}
/**
+ * 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 @@
* @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 @@
* @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 @@
* @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 @@
* 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 @@
* 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 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 @@
* {@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,93 @@
* {@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();
+ }
+ }
+
+ /**
+ * 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
+ * no-op.
+ *
+ * @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(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ boolean isProvisioned) {
+ try {
+ getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isProvisioned);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -1321,7 +1606,14 @@
* does not support the capability/technology combination specified, this operation will be a
* no-op.
*
- * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+ * <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.
*/
@@ -1329,31 +1621,92 @@
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setRcsProvisioningStatusForCapability(
@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
- boolean isProvisioned) {
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) {
try {
getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
- isProvisioned);
+ 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 @@
* <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 @@
/**
* 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 @@
* <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 @@
* 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 @@
* <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 @@
* <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 @@
* 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 @@
* <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 @@
* @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 @@
* {@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 c25ace0..f367e40 100644
--- a/telephony/java/android/telephony/ims/RcsClientConfiguration.java
+++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
@@ -34,7 +34,7 @@
/**@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 @@
* 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 @@
* @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 @@
* @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/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 9112118..9c36db8 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -221,6 +221,15 @@
}
/**
+ * Set the entity URI related to the contact whose capabilities were requested.
+ * @param entityUri the 'pres' URL of the PRESENTITY publishing presence document.
+ */
+ public @NonNull PresenceBuilder setEntityUri(@NonNull Uri entityUri) {
+ mCapabilities.mEntityUri = entityUri;
+ return this;
+ }
+
+ /**
* @return the RcsContactUceCapability instance.
*/
public @NonNull RcsContactUceCapability build() {
@@ -232,6 +241,7 @@
private @SourceType int mSourceType;
private @CapabilityMechanism int mCapabilityMechanism;
private @RequestResult int mRequestResult;
+ private Uri mEntityUri;
private final Set<String> mFeatureTags = new HashSet<>();
private final List<RcsContactPresenceTuple> mPresenceTuples = new ArrayList<>();
@@ -248,6 +258,7 @@
mCapabilityMechanism = in.readInt();
mSourceType = in.readInt();
mRequestResult = in.readInt();
+ mEntityUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
List<String> featureTagList = new ArrayList<>();
in.readStringList(featureTagList);
mFeatureTags.addAll(featureTagList);
@@ -260,6 +271,7 @@
out.writeInt(mCapabilityMechanism);
out.writeInt(mSourceType);
out.writeInt(mRequestResult);
+ out.writeParcelable(mEntityUri, flags);
out.writeStringList(new ArrayList<>(mFeatureTags));
out.writeParcelableList(mPresenceTuples, flags);
}
@@ -361,6 +373,15 @@
return mContactUri;
}
+ /**
+ * Retrieve the entity URI of the contact whose presence information is being requested for.
+ * @return the URI representing the 'pres' URL of the PRESENTITY publishing presence document
+ * or {@code null} if the entity uri does not exist in the presence document.
+ */
+ public @Nullable Uri getEntityUri() {
+ return mEntityUri;
+ }
+
@Override
public String toString() {
StringBuilder builder = new StringBuilder("RcsContactUceCapability");
@@ -382,6 +403,13 @@
builder.append(mSourceType);
builder.append(", requestResult=");
builder.append(mRequestResult);
+ if (Build.IS_ENG) {
+ builder.append("entity uri=");
+ builder.append(mEntityUri != null ? mEntityUri : "null");
+ } else {
+ builder.append("entity uri (isNull)=");
+ builder.append(mEntityUri != null ? "XXX" : "null");
+ }
if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) {
builder.append(", presenceTuples={");
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 0000000..63ec4aa
--- /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 c6966b3..ae6166f 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -32,18 +32,19 @@
*/
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 9a3f592..ad2e9e1 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.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 @@
public class MmTelFeature extends ImsFeature {
private static final String LOG_TAG = "MmTelFeature";
+ private Executor mExecutor;
/**
* @hide
@@ -68,160 +78,261 @@
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 @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 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 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 @@
*/
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 @@
*/
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 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 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 18cc37d..70e4ef1 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -59,9 +59,7 @@
/**
* 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 @@
// 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 @@
* 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 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 @@
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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 @@
* 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 @@
/**
* 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 @@
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 a3a6cb8..e810095 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.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 @@
// 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 @@
}
}
+ 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 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 d75da90..11fc328 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -33,12 +33,21 @@
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 @@
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 @@
* 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 @@
* @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 @@
* {@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 @@
* {@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 @@
@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 @@
@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 @@
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 @@
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 @@
* @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 @@
* @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 @@
}
});
}
+
+ /**
+ * 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 8ad40ed..84b2253 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 @@
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 @@
+ "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 @@
}
}
}
+
+ /**
+ * 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 ec1c7b3..a723cd8 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 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 @@
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 @@
+ "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 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 02bcdec..ac5565b 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.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 @@
* <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 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 @@
// 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 @@
* 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 @@
* <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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* {@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 @@
*
* 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 @@
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 eb3e8ed..11cdeed 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -27,10 +27,17 @@
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 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 @@
+ "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 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 13ea9973..52538cb 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -86,10 +86,21 @@
}
};
- 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 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 f5f67bd..416096b 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
@@ -23,11 +23,11 @@
* {@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/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 167aa07..0ac7cf9 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.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 @@
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 @@
/**
* 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 @@
* @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/test-base/Android.bp b/test-base/Android.bp
index 8be7324..527159a 100644
--- a/test-base/Android.bp
+++ b/test-base/Android.bp
@@ -72,11 +72,16 @@
// Build the android.test.base_static library
// ==========================================
-// This is only intended for inclusion in the android.test.runner-minus-junit,
-// robolectric_android-all-stub and repackaged.android.test.* libraries.
+// This is only intended for use by the android.test.runner-minus-junit
+// library.
+//
// Must not be used elsewhere.
+//
java_library_static {
name: "android.test.base_static",
+ visibility: [
+ "//frameworks/base/test-runner",
+ ],
installable: false,
srcs: [":android-test-base-sources"],
@@ -91,28 +96,10 @@
sdk_version: "current",
}
-// Build the repackaged.android.test.base library
-// ==============================================
-// This contains repackaged versions of the classes from
-// android.test.base.
-java_library_static {
- name: "repackaged.android.test.base",
-
- sdk_version: "current",
- static_libs: ["android.test.base_static"],
-
- jarjar_rules: "jarjar-rules.txt",
- // Pin java_version until jarjar is certified to support later versions. http://b/72703434
- java_version: "1.8",
-}
-
// Build the android.test.base-minus-junit library
// ===============================================
// This contains the android.test classes from android.test.base plus
-// the com.android.internal.util.Predicate[s] classes. This is only
-// intended for inclusion in android.test.legacy and in
-// android.test.base-hiddenapi-annotations to avoid a dependency cycle and must
-// not be used elsewhere.
+// the com.android.internal.util.Predicate[s] classes.
java_library_static {
name: "android.test.base-minus-junit",
diff --git a/test-base/jarjar-rules.txt b/test-base/jarjar-rules.txt
deleted file mode 100644
index fd8555c..0000000
--- a/test-base/jarjar-rules.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-rule junit.** repackaged.junit.@1
-rule android.test.** repackaged.android.test.@1
-rule com.android.internal.util.** repackaged.com.android.internal.util.@1
diff --git a/test-runner/Android.bp b/test-runner/Android.bp
index 2a19af9..13a5dac 100644
--- a/test-runner/Android.bp
+++ b/test-runner/Android.bp
@@ -79,32 +79,6 @@
],
}
-// Build the repackaged.android.test.runner library
-// ================================================
-java_library_static {
- name: "repackaged.android.test.runner",
-
- srcs: [":android-test-runner-sources"],
- exclude_srcs: [
- "src/android/test/ActivityUnitTestCase.java",
- "src/android/test/ApplicationTestCase.java",
- "src/android/test/IsolatedContext.java",
- "src/android/test/ProviderTestCase.java",
- "src/android/test/ProviderTestCase2.java",
- "src/android/test/RenamingDelegatingContext.java",
- "src/android/test/ServiceTestCase.java",
- ],
-
- sdk_version: "current",
- libs: [
- "android.test.base_static",
- ],
-
- jarjar_rules: "jarjar-rules.txt",
- // Pin java_version until jarjar is certified to support later versions. http://b/72703434
- java_version: "1.8",
-}
-
// Make the current.txt available for use by the cts/tests/signature tests.
// ========================================================================
filegroup {
diff --git a/test-runner/jarjar-rules.txt b/test-runner/jarjar-rules.txt
deleted file mode 120000
index f6f7913..0000000
--- a/test-runner/jarjar-rules.txt
+++ /dev/null
@@ -1 +0,0 @@
-../test-base/jarjar-rules.txt
\ No newline at end of file
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.bp
new file mode 100644
index 0000000..4fff969
--- /dev/null
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2013 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "frameworks_base_license",
+ ],
+}
+
+android_test {
+ name: "SmartCamera",
+ optimize: {
+ enabled: false,
+ },
+ // comment it out for now since we need use some hidden APIs
+ sdk_version: "current",
+ static_libs: ["android-ex-camera2"],
+ srcs: [
+ "src/**/*.java",
+ ],
+ jni_libs: ["libsmartcamera_jni"],
+}
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.mk
deleted file mode 100644
index 6003628..0000000
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2013 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.
-
-ifneq ($(TARGET_BUILD_JAVA_SUPPORT_LEVEL),)
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-# comment it out for now since we need use some hidden APIs
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-ex-camera2
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
- $(call all-renderscript-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmartCamera
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../NOTICE
-LOCAL_JNI_SHARED_LIBRARIES := libsmartcamera_jni
-
-include $(BUILD_PACKAGE)
-
-# Include packages in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
-endif
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.bp
new file mode 100644
index 0000000..5edb1de
--- /dev/null
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2013 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "frameworks_base_license",
+ ],
+}
+
+android_test {
+ name: "SmartCamera-tests",
+ platform_apis: true,
+ srcs: ["src/**/*.java"],
+ libs: ["android.test.base"],
+ static_libs: [
+ "guava",
+ "junit",
+ ],
+ optimize: {
+ enabled: false,
+ },
+ instrumentation_for: "SmartCamera",
+}
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk b/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk
deleted file mode 100644
index c23d593..0000000
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/tests/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2013 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PACKAGE_NAME := SmartCamera-tests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../../NOTICE
-
-LOCAL_SRC_FILES += $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := guava junit
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_INSTRUMENTATION_FOR := SmartCamera
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CanvasCompare/Android.bp b/tests/CanvasCompare/Android.bp
new file mode 100644
index 0000000..9883115
--- /dev/null
+++ b/tests/CanvasCompare/Android.bp
@@ -0,0 +1,63 @@
+//
+// 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "frameworks_base_license",
+ ],
+}
+
+android_test {
+ name: "CanvasCompare",
+ srcs: [
+ "src/**/*.java",
+ ":CanvasCompare-rscript{CanvasCompare.srcjar}",
+ ],
+ resource_zips: [
+ ":CanvasCompare-rscript{CanvasCompare.res.zip}",
+ ],
+ platform_apis: true,
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+}
+
+genrule {
+ name: "CanvasCompare-rscript",
+ srcs: [
+ "src/**/*.rscript",
+ ":rs_script_api",
+ ":rs_clang_headers",
+ ],
+ tools: [
+ "llvm-rs-cc",
+ "soong_zip",
+ ],
+ out: [
+ "CanvasCompare.srcjar",
+ "CanvasCompare.res.zip",
+ ],
+ cmd: "for f in $(locations src/**/*.rscript); do " +
+ " $(location llvm-rs-cc) -o $(genDir)/res/raw -p $(genDir)/src " +
+ " -I $$(dirname $$(echo $(locations :rs_script_api) | awk '{ print $$1 }')) " +
+ " -I $$(dirname $$(echo $(locations :rs_clang_headers) | awk '{ print $$1 }')) $${f}; " +
+ "done && " +
+ "$(location soong_zip) -srcjar -o $(location CanvasCompare.srcjar) -C $(genDir)/src -D $(genDir)/src &&" +
+ "$(location soong_zip) -o $(location CanvasCompare.res.zip) -C $(genDir)/res -D $(genDir)/res",
+}
diff --git a/tests/CanvasCompare/Android.mk b/tests/CanvasCompare/Android.mk
deleted file mode 100644
index b82ae65..0000000
--- a/tests/CanvasCompare/Android.mk
+++ /dev/null
@@ -1,33 +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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
-
-LOCAL_PACKAGE_NAME := CanvasCompare
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml
index c30d761..21256d8 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 0000000..173ca99
--- /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 0000000..bd8942d
--- /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 0000000..f13c088
--- /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 0000000..66edbb5
--- /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 9ed8d2f..7132ae8 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_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 @@
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 @@
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 0000000..9d17d38
--- /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/TrustTests/OWNERS b/tests/TrustTests/OWNERS
new file mode 100644
index 0000000..e2c6ce1
--- /dev/null
+++ b/tests/TrustTests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/trust/OWNERS
diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp
deleted file mode 100644
index f87ca2e..0000000
--- 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 ef014f0..0000000
--- 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 aa87958..0000000
--- 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 41f73cd..228520e 100644
--- a/tests/vcn/Android.bp
+++ b/tests/vcn/Android.bp
@@ -18,6 +18,7 @@
"java/**/*.kt",
],
platform_apis: true,
+ defaults: ["framework-connectivity-test-defaults"],
test_suites: ["device-tests"],
certificate: "platform",
static_libs: [
@@ -28,6 +29,7 @@
"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 2ad9aac..a8f657c 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>
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 978bf3e..7b1f7a5 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -174,7 +174,7 @@
private IntentFilter getIntentFilter() {
final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
- verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
+ verify(mContext).registerReceiver(any(), captor.capture(), any(), any(), anyInt());
return captor.getValue();
}
@@ -258,7 +258,8 @@
eq(mTelephonySubscriptionTracker),
any(IntentFilter.class),
any(),
- eq(mHandler));
+ eq(mHandler),
+ eq(Context.RECEIVER_NOT_EXPORTED));
final IntentFilter filter = getIntentFilter();
assertEquals(2, filter.countActions());
assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index e547400..4cfa93b 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -307,7 +307,10 @@
ncCaptor.capture(),
lpCaptor.capture(),
any(),
- argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE),
+ // Subtype integer/name and extras do not have getters; cannot be tested.
+ argThat(nac -> nac.getLegacyType() == ConnectivityManager.TYPE_MOBILE
+ && nac.getLegacyTypeName().equals(
+ VcnGatewayConnection.NETWORK_INFO_NETWORK_TYPE_STRING)),
any(),
any(),
any());
diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp
index 01eb4f6..cc10db9 100644
--- a/tools/aapt/Android.bp
+++ b/tools/aapt/Android.bp
@@ -61,16 +61,6 @@
enabled: true,
},
},
-
- // This tool is prebuilt if we're doing an app-only build.
- product_variables: {
- pdk: {
- enabled: false,
- },
- unbundled_build: {
- enabled: false,
- },
- },
}
// ==========================================================
diff --git a/tools/bit/command.cpp b/tools/bit/command.cpp
index f95ea11..6c68e0b 100644
--- a/tools/bit/command.cpp
+++ b/tools/bit/command.cpp
@@ -192,10 +192,11 @@
if (strchr(prog, '/') != NULL) {
return execve(prog, (char*const*)argv, (char*const*)envp);
} else {
- char* pathEnv = strdup(getenv("PATH"));
- if (pathEnv == NULL) {
+ const char* pathEnvRaw = getenv("PATH");
+ if (pathEnvRaw == NULL) {
return 1;
}
+ char* pathEnv = strdup(pathEnvRaw);
char* dir = pathEnv;
while (dir) {
char* next = strchr(dir, ':');
diff --git a/tools/streaming_proto/Android.bp b/tools/streaming_proto/Android.bp
index 1ec83a3..b18bdff 100644
--- a/tools/streaming_proto/Android.bp
+++ b/tools/streaming_proto/Android.bp
@@ -69,7 +69,6 @@
"test/**/*.proto",
],
proto: {
- plugin: "javastream",
+ type: "stream",
},
- static_libs: ["libprotobuf-java-lite"],
}