Merge "audio: fix spelling mistakes"
diff --git a/.clang-format b/.clang-format
index 03af56d..021d938 100644
--- a/.clang-format
+++ b/.clang-format
@@ -2,7 +2,7 @@
AccessModifierOffset: -4
AlignOperands: false
-AllowShortFunctionsOnASingleLine: Inline
+AllowShortFunctionsOnASingleLine: Empty
AlwaysBreakBeforeMultilineStrings: false
ColumnLimit: 100
CommentPragmas: NOLINT:.*
diff --git a/Android.bp b/Android.bp
index 62d2632..b4e02c0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -345,6 +345,7 @@
"framework-permission-aidl-java",
"spatializer-aidl-java",
"audiopolicy-types-aidl-java",
+ "modules-utils-expresslog",
],
}
@@ -531,7 +532,7 @@
"core/java/**/*.logtags",
"**/package.html",
],
- visibility: ["//visibility:private"],
+ visibility: ["//frameworks/base/api"],
}
// Defaults for all stubs that include the non-updatable framework. These defaults do not include
@@ -545,12 +546,10 @@
java_version: "1.8",
arg_files: [":frameworks-base-core-AndroidManifest.xml"],
aidl: {
- local_include_dirs: [
- "media/aidl",
- "telephony/java",
- ],
include_dirs: [
"frameworks/av/aidl",
+ "frameworks/base/media/aidl",
+ "frameworks/base/telephony/java",
"frameworks/native/libs/permission/aidl",
"packages/modules/Bluetooth/framework/aidl-export",
"packages/modules/Connectivity/framework/aidl-export",
@@ -582,7 +581,7 @@
annotations_enabled: true,
previous_api: ":android.api.public.latest",
merge_annotations_dirs: ["metalava-manual"],
- defaults_visibility: ["//visibility:private"],
+ defaults_visibility: ["//frameworks/base/api"],
visibility: ["//frameworks/base/api"],
}
@@ -610,12 +609,9 @@
// NOTE: The below can be removed once the prebuilt stub contains IKE.
"sdk_system_current_android.net.ipsec.ike",
],
- defaults_visibility: ["//visibility:private"],
}
build = [
- "StubLibraries.bp",
- "ApiDocs.bp",
"ProtoLibraries.bp",
"TestProtoLibraries.bp",
]
diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp
index 9064b44..2590fe3 100644
--- a/apct-tests/perftests/blobstore/Android.bp
+++ b/apct-tests/perftests/blobstore/Android.bp
@@ -29,7 +29,7 @@
"androidx.test.rules",
"androidx.annotation_annotation",
"apct-perftests-utils",
- "ub-uiautomator",
+ "androidx.test.uiautomator_uiautomator",
"collector-device-lib-platform",
"androidx.benchmark_benchmark-macro",
],
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java
index 0208dab..4e4780f 100644
--- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/AtraceUtils.java
@@ -21,10 +21,10 @@
import android.os.ParcelFileDescriptor;
import android.perftests.utils.TraceMarkParser;
import android.perftests.utils.TraceMarkParser.TraceMarkSlice;
-import android.support.test.uiautomator.UiDevice;
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import java.io.BufferedReader;
import java.io.IOException;
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
index 03e5468..3cd9f50 100644
--- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
@@ -25,12 +25,12 @@
import android.perftests.utils.PerfManualStatusReporter;
import android.perftests.utils.TraceMarkParser;
import android.perftests.utils.TraceMarkParser.TraceMarkSlice;
-import android.support.test.uiautomator.UiDevice;
import android.util.DataUnit;
import androidx.benchmark.macro.MacrobenchmarkScope;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import com.android.utils.blob.FakeBlobData;
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
index b995b06..3910a08 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ExpensiveObjectsPerfTest.java
@@ -52,7 +52,7 @@
}
}
- @Test
+ @Test(timeout = 900)
public void timeClonedDateFormatTimeInstance() {
DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
index c967e51..45c6b8c 100644
--- a/apct-tests/perftests/multiuser/Android.bp
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -31,6 +31,9 @@
],
platform_apis: true,
test_suites: ["device-tests"],
- data: ["trace_configs/*"],
+ data: [
+ ":MultiUserPerfDummyApp",
+ "trace_configs/*",
+ ],
certificate: "platform",
}
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
index 81cec91..b6ea54d 100644
--- a/apct-tests/perftests/packagemanager/Android.bp
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -33,7 +33,59 @@
test_suites: ["device-tests"],
- data: [":perfetto_artifacts"],
+ data: [
+ ":QueriesAll4",
+ ":QueriesAll31",
+ ":QueriesAll43",
+ ":QueriesAll15",
+ ":QueriesAll27",
+ ":QueriesAll39",
+ ":QueriesAll11",
+ ":QueriesAll23",
+ ":QueriesAll35",
+ ":QueriesAll47",
+ ":QueriesAll9",
+ ":QueriesAll19",
+ ":QueriesAll1",
+ ":QueriesAll5",
+ ":QueriesAll40",
+ ":QueriesAll20",
+ ":QueriesAll32",
+ ":QueriesAll48",
+ ":QueriesAll16",
+ ":QueriesAll28",
+ ":QueriesAll44",
+ ":QueriesAll12",
+ ":QueriesAll24",
+ ":QueriesAll36",
+ ":QueriesAll6",
+ ":QueriesAll2",
+ ":QueriesAll41",
+ ":QueriesAll21",
+ ":QueriesAll37",
+ ":QueriesAll49",
+ ":QueriesAll17",
+ ":QueriesAll29",
+ ":QueriesAll33",
+ ":QueriesAll45",
+ ":QueriesAll13",
+ ":QueriesAll25",
+ ":QueriesAll7",
+ ":QueriesAll3",
+ ":QueriesAll30",
+ ":QueriesAll42",
+ ":QueriesAll10",
+ ":QueriesAll26",
+ ":QueriesAll38",
+ ":QueriesAll18",
+ ":QueriesAll22",
+ ":QueriesAll34",
+ ":QueriesAll46",
+ ":QueriesAll14",
+ ":QueriesAll8",
+ ":QueriesAll0",
+ ":perfetto_artifacts",
+ ],
certificate: "platform",
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
index 80a70a6..1cd1a46 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -31,7 +31,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.expresslog.Counter;
+import com.android.modules.expresslog.Counter;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
diff --git a/api/Android.bp b/api/Android.bp
index 9d20eca..f40f0c9 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -252,3 +252,8 @@
out: ["api_fingerprint.txt"],
cmd: "cat $(in) | md5sum | cut -d' ' -f1 > $(out)",
}
+
+build = [
+ "ApiDocs.bp",
+ "StubLibraries.bp",
+]
diff --git a/ApiDocs.bp b/api/ApiDocs.bp
similarity index 97%
rename from ApiDocs.bp
rename to api/ApiDocs.bp
index a46ecce..fbcaa52 100644
--- a/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -182,10 +182,10 @@
// using droiddoc
/////////////////////////////////////////////////////////////////////
-framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+framework_docs_only_args = " -android -manifest $(location :frameworks-base-core-AndroidManifest.xml) " +
"-metalavaApiSince " +
"-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
- "-overview $(location core/java/overview.html) " +
+ "-overview $(location :frameworks-base-java-overview) " +
// Federate Support Library references against local API file.
"-federate SupportLib https://developer.android.com " +
"-federationapi SupportLib $(location :current-support-api) " +
@@ -218,16 +218,16 @@
"sdk.preview 0",
],
arg_files: [
- "core/res/AndroidManifest.xml",
- "core/java/overview.html",
+ ":frameworks-base-core-AndroidManifest.xml",
+ ":frameworks-base-java-overview",
":current-support-api",
":current-androidx-api",
],
// TODO(b/169090544): remove below aidl includes.
aidl: {
- local_include_dirs: ["media/aidl"],
include_dirs: [
"frameworks/av/aidl",
+ "frameworks/base/media/aidl",
"frameworks/native/libs/permission/aidl",
],
},
diff --git a/StubLibraries.bp b/api/StubLibraries.bp
similarity index 99%
rename from StubLibraries.bp
rename to api/StubLibraries.bp
index b005591..f08745b 100644
--- a/StubLibraries.bp
+++ b/api/StubLibraries.bp
@@ -515,6 +515,7 @@
],
api_levels_sdk_type: "public",
extensions_info_file: ":sdk-extensions-info",
+ visibility: ["//frameworks/base"],
}
droidstubs {
diff --git a/api/api.go b/api/api.go
index 09c2383..af817b5 100644
--- a/api/api.go
+++ b/api/api.go
@@ -15,7 +15,9 @@
package api
import (
+ "fmt"
"sort"
+ "strings"
"github.com/google/blueprint/proptools"
@@ -102,6 +104,13 @@
Visibility []string
}
+type defaultsProps struct {
+ Name *string
+ Api_surface *string
+ Api_contributions []string
+ Defaults_visibility []string
+}
+
type Bazel_module struct {
Bp2build_available *bool
}
@@ -164,26 +173,26 @@
}
func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
- for _, i := range []struct{
+ for _, i := range []struct {
name string
tag string
modules []string
}{
{
- name: "all-modules-public-annotations",
- tag: "{.public.annotations.zip}",
+ name: "all-modules-public-annotations",
+ tag: "{.public.annotations.zip}",
modules: modules,
}, {
- name: "all-modules-system-annotations",
- tag: "{.system.annotations.zip}",
+ name: "all-modules-system-annotations",
+ tag: "{.system.annotations.zip}",
modules: modules,
}, {
- name: "all-modules-module-lib-annotations",
- tag: "{.module-lib.annotations.zip}",
+ name: "all-modules-module-lib-annotations",
+ tag: "{.module-lib.annotations.zip}",
modules: modules,
}, {
- name: "all-modules-system-server-annotations",
- tag: "{.system-server.annotations.zip}",
+ name: "all-modules-system-server-annotations",
+ tag: "{.system-server.annotations.zip}",
modules: system_server_modules,
},
} {
@@ -329,6 +338,30 @@
}
}
+func createApiContributionDefaults(ctx android.LoadHookContext, modules []string) {
+ defaultsSdkKinds := []android.SdkKind{
+ android.SdkPublic, android.SdkSystem, android.SdkModule,
+ }
+ for _, sdkKind := range defaultsSdkKinds {
+ props := defaultsProps{}
+ props.Name = proptools.StringPtr(
+ sdkKind.DefaultJavaLibraryName() + "_contributions")
+ if sdkKind == android.SdkModule {
+ props.Name = proptools.StringPtr(
+ sdkKind.DefaultJavaLibraryName() + "_contributions_full")
+ }
+ props.Api_surface = proptools.StringPtr(sdkKind.String())
+ apiSuffix := ""
+ if sdkKind != android.SdkPublic {
+ apiSuffix = "." + strings.ReplaceAll(sdkKind.String(), "-", "_")
+ }
+ props.Api_contributions = transformArray(
+ modules, "", fmt.Sprintf(".stubs.source%s.api.contribution", apiSuffix))
+ props.Defaults_visibility = []string{"//visibility:public"}
+ ctx.CreateModule(java.DefaultsFactory, &props)
+ }
+}
+
func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
bootclasspath := a.properties.Bootclasspath
system_server_classpath := a.properties.System_server_classpath
@@ -347,6 +380,8 @@
createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath)
createPublicStubsSourceFilegroup(ctx, bootclasspath)
+
+ createApiContributionDefaults(ctx, bootclasspath)
}
func combinedApisModuleFactory() android.Module {
@@ -374,7 +409,7 @@
"system-server": "-system-server-current.txt",
}
- for scopeName, suffix := range scopeToSuffix{
+ for scopeName, suffix := range scopeToSuffix {
name := a.Name() + suffix
var scope bazel.StringAttribute
diff --git a/api/docs b/api/docs
new file mode 120000
index 0000000..a9594bf
--- /dev/null
+++ b/api/docs
@@ -0,0 +1 @@
+../docs
\ No newline at end of file
diff --git a/boot/OWNERS b/boot/OWNERS
index 0e258d0..3fe1a41 100644
--- a/boot/OWNERS
+++ b/boot/OWNERS
@@ -2,5 +2,5 @@
file:platform/build/soong:/OWNERS
# art-team@ manages the boot image profiles for frameworks
-per-file boot-* = calin@google.com, yawanng@google.com, ngeoffray@google.com
-per-file preloaded-classes* = calin@google.com, yawanng@google.com, ngeoffray@google.com
+per-file boot-* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com
+per-file preloaded-classes* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6b6bc97..27dadda 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -107,6 +107,7 @@
static const char DISPLAYS_PROP_NAME[] = "persist.service.bootanim.displays";
static const char CLOCK_ENABLED_PROP_NAME[] = "persist.sys.bootanim.clock.enabled";
static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
+static const int MAX_CHECK_EXIT_INTERVAL_US = 50000;
static constexpr size_t TEXT_POS_LEN_MAX = 16;
static const int DYNAMIC_COLOR_COUNT = 4;
static const char U_TEXTURE[] = "uTexture";
@@ -1680,7 +1681,17 @@
checkExit();
}
- usleep(part.pause * ns2us(frameDuration));
+ int pauseDuration = part.pause * ns2us(frameDuration);
+ while(pauseDuration > 0 && !exitPending()){
+ if (pauseDuration > MAX_CHECK_EXIT_INTERVAL_US) {
+ usleep(MAX_CHECK_EXIT_INTERVAL_US);
+ pauseDuration -= MAX_CHECK_EXIT_INTERVAL_US;
+ } else {
+ usleep(pauseDuration);
+ break;
+ }
+ checkExit();
+ }
if (exitPending() && !part.count && mCurrentInset >= mTargetInset &&
!part.hasFadingPhase()) {
diff --git a/config/OWNERS b/config/OWNERS
index 74813bc..6a5df76 100644
--- a/config/OWNERS
+++ b/config/OWNERS
@@ -1,8 +1,8 @@
include /ZYGOTE_OWNERS
# art-team@ manages the boot image profiles
-per-file boot-* = ngeoffray@google.com, vmarko@google.com
-per-file dirty-image-objects = ngeoffray@google.com, vmarko@google.com
-per-file generate-preloaded-classes.sh = ngeoffray@google.com, vmarko@google.com
-per-file preloaded-classes* = ngeoffray@google.com, vmarko@google.com
+per-file boot-* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com
+per-file dirty-image-objects = ishcheikin@google.com, ngeoffray@google.com, vmarko@google.com
+per-file generate-preloaded-classes.sh = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com
+per-file preloaded-classes* = islamelbanna@google.com, ngeoffray@google.com, vmarko@google.com
diff --git a/core/api/current.txt b/core/api/current.txt
index b243374..77a6fec 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -18727,8 +18727,8 @@
method public int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int, int);
method public boolean claimInterface(android.hardware.usb.UsbInterface, boolean);
method public void close();
- method public int controlTransfer(int, int, int, int, byte[], int, int);
- method public int controlTransfer(int, int, int, int, byte[], int, int, int);
+ method public int controlTransfer(int, int, int, int, @Nullable byte[], int, int);
+ method public int controlTransfer(int, int, int, int, @Nullable byte[], int, int, int);
method public int getFileDescriptor();
method public byte[] getRawDescriptors();
method public String getSerial();
@@ -31081,6 +31081,7 @@
field public static final int S_V2 = 32; // 0x20
field public static final int TIRAMISU = 33; // 0x21
field public static final int UPSIDE_DOWN_CAKE = 10000; // 0x2710
+ field public static final int VANILLA_ICE_CREAM = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
@@ -41362,6 +41363,8 @@
field public static final String KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY = "carrier_nr_availabilities_int_array";
field public static final String KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL = "carrier_provisions_wifi_merged_networks_bool";
field public static final String KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL = "carrier_rcs_provisioning_required_bool";
+ field public static final String KEY_CARRIER_SERVICE_NAME_STRING_ARRAY = "carrier_service_name_array";
+ field public static final String KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY = "carrier_service_number_array";
field public static final String KEY_CARRIER_SETTINGS_ACTIVITY_COMPONENT_NAME_STRING = "carrier_settings_activity_component_name_string";
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";
@@ -41402,6 +41405,7 @@
field public static final String KEY_DATA_LIMIT_NOTIFICATION_BOOL = "data_limit_notification_bool";
field public static final String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
field public static final String KEY_DATA_RAPID_NOTIFICATION_BOOL = "data_rapid_notification_bool";
+ field public static final String KEY_DATA_SWITCH_VALIDATION_MIN_INTERVAL_MILLIS_LONG = "data_switch_validation_min_gap_long";
field public static final String KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG = "data_switch_validation_timeout_long";
field public static final String KEY_DATA_WARNING_NOTIFICATION_BOOL = "data_warning_notification_bool";
field public static final String KEY_DATA_WARNING_THRESHOLD_BYTES_LONG = "data_warning_threshold_bytes_long";
@@ -42743,9 +42747,12 @@
method public int getDomain();
method @Nullable public String getRegisteredPlmn();
method public int getTransportType();
- method public boolean isRegistered();
- method public boolean isRoaming();
- method public boolean isSearching();
+ method public boolean isNetworkRegistered();
+ method public boolean isNetworkRoaming();
+ method public boolean isNetworkSearching();
+ method @Deprecated public boolean isRegistered();
+ method @Deprecated public boolean isRoaming();
+ method @Deprecated public boolean isSearching();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.NetworkRegistrationInfo> CREATOR;
field public static final int DOMAIN_CS = 1; // 0x1
@@ -43499,6 +43506,7 @@
method public int describeContents();
method public int getNetworkType();
method public int getOverrideNetworkType();
+ method public boolean isRoaming();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.TelephonyDisplayInfo> CREATOR;
field public static final int OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO = 2; // 0x2
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index c6c4daf..13a4899 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -17,10 +17,19 @@
public class ActivityManager {
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
+ method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]);
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void registerUidFrozenStateChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
}
+ public static interface ActivityManager.UidFrozenStateChangedCallback {
+ method public void onUidFrozenStateChanged(@NonNull int[], @NonNull int[]);
+ field public static final int UID_FROZEN_STATE_FROZEN = 1; // 0x1
+ field public static final int UID_FROZEN_STATE_UNFROZEN = 2; // 0x2
+ }
+
public class AppOpsManager {
field public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage";
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 398b596..821944f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12828,7 +12828,8 @@
public final class NetworkRegistrationInfo implements android.os.Parcelable {
method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo();
- method public int getRegistrationState();
+ method public int getNetworkRegistrationState();
+ method @Deprecated public int getRegistrationState();
method public int getRejectCause();
method public int getRoamingType();
method public boolean isEmergencyEnabled();
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 025e862..0100f0e 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -143,12 +143,16 @@
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioFocusRequest.Builder.setOnAudioFocusChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRouting.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.MediaCodec#setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaCodec.setOnFrameRenderedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.MediaPlayer#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6a5ef3a..dc01662 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -122,16 +122,19 @@
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
method public void alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName);
method public long getTotalRam();
+ method @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int[] getUidFrozenState(@NonNull int[]);
method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessCapabilities(int);
method @RequiresPermission(allOf={android.Manifest.permission.PACKAGE_USAGE_STATS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional=true) public int getUidProcessState(int);
method public void holdLock(android.os.IBinder, int);
method public static boolean isHighEndGfx();
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void registerUidFrozenStateChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
method @RequiresPermission(android.Manifest.permission.RESET_APP_ERRORS) public void resetAppErrors();
method public static void resumeAppSwitches() throws android.os.RemoteException;
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void setStopUserOnSwitch(int);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean stopUser(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void unregisterUidFrozenStateChangedCallback(@NonNull android.app.ActivityManager.UidFrozenStateChangedCallback);
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String);
method @RequiresPermission(android.Manifest.permission.DUMP) public void waitForBroadcastIdle();
field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL
@@ -161,6 +164,12 @@
method @Nullable public String getIconResourcePackage();
}
+ public static interface ActivityManager.UidFrozenStateChangedCallback {
+ method public void onUidFrozenStateChanged(@NonNull int[], @NonNull int[]);
+ field public static final int UID_FROZEN_STATE_FROZEN = 1; // 0x1
+ field public static final int UID_FROZEN_STATE_UNFROZEN = 2; // 0x2
+ }
+
public class ActivityOptions {
method public boolean isEligibleForLegacyPermissionPrompt();
method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
@@ -3469,7 +3478,7 @@
public class WindowOrganizer {
ctor public WindowOrganizer();
- method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
method @RequiresPermission(value=android.Manifest.permission.MANAGE_ACTIVITY_TASKS, conditional=true) public void applyTransaction(@NonNull android.window.WindowContainerTransaction);
}
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 7df3d1e..8ceea92 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -429,6 +429,11 @@
},
}
+filegroup {
+ name: "frameworks-base-java-overview",
+ srcs: ["overview.html"],
+}
+
// Avoid including Parcelable classes as we don't want to have two copies of
// Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony)
// and TeleService app (packages/services/Telephony).
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index c17fbf1..dd95540 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -2523,6 +2523,10 @@
IAccessibilityServiceConnection connection =
AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
if (mInfo != null && connection != null) {
+ if (!mInfo.isWithinParcelableSize()) {
+ throw new IllegalStateException(
+ "Cannot update service info: size is larger than safe parcelable limits.");
+ }
try {
connection.setServiceInfo(mInfo);
mInfo = null;
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 530de0f..0cbcdb5 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -40,6 +40,7 @@
import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
@@ -1128,6 +1129,15 @@
return 0;
}
+ /** @hide */
+ public final boolean isWithinParcelableSize() {
+ final Parcel parcel = Parcel.obtain();
+ writeToParcel(parcel, 0);
+ final boolean result = parcel.dataSize() <= IBinder.MAX_IPC_SIZE;
+ parcel.recycle();
+ return result;
+ }
+
public void writeToParcel(Parcel parcel, int flagz) {
parcel.writeInt(eventTypes);
parcel.writeStringArray(packageNames);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d24b677..e85fa9d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -959,7 +959,7 @@
private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE;
private SpannableStringBuilder mDefaultKeySsb = null;
- private ActivityManager.TaskDescription mTaskDescription =
+ private final ActivityManager.TaskDescription mTaskDescription =
new ActivityManager.TaskDescription();
protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
@@ -970,7 +970,7 @@
private Thread mUiThread;
@UnsupportedAppUsage
- ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
+ final ActivityTransitionState mActivityTransitionState = new ActivityTransitionState();
SharedElementCallback mEnterTransitionListener = SharedElementCallback.NULL_CALLBACK;
SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK;
@@ -1839,7 +1839,7 @@
final int numDialogs = ids.length;
mManagedDialogs = new SparseArray<ManagedDialog>(numDialogs);
for (int i = 0; i < numDialogs; i++) {
- final Integer dialogId = ids[i];
+ final int dialogId = ids[i];
Bundle dialogState = b.getBundle(savedDialogKeyFor(dialogId));
if (dialogState != null) {
// Calling onRestoreInstanceState() below will invoke dispatchOnCreate
@@ -1909,7 +1909,7 @@
* <code>persistAcrossReboots</code>.
*
* @param savedInstanceState The data most recently supplied in {@link #onSaveInstanceState}
- * @param persistentState The data caming from the PersistableBundle first
+ * @param persistentState The data coming from the PersistableBundle first
* saved in {@link #onSaveInstanceState(Bundle, PersistableBundle)}.
*
* @see #onCreate
@@ -5058,7 +5058,7 @@
* This hook is called when the user signals the desire to start a search.
*
* <p>You can use this function as a simple way to launch the search UI, in response to a
- * menu item, search button, or other widgets within your activity. Unless overidden,
+ * menu item, search button, or other widgets within your activity. Unless overridden,
* calling this function is the same as calling
* {@link #startSearch startSearch(null, false, null, false)}, which launches
* search for the current activity as specified in its manifest, see {@link SearchManager}.
@@ -8797,7 +8797,7 @@
* @see Activity#convertFromTranslucent()
* @see Activity#convertToTranslucent(TranslucentConversionListener, ActivityOptions)
*/
- public void onTranslucentConversionComplete(boolean drawComplete);
+ void onTranslucentConversionComplete(boolean drawComplete);
}
private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
@@ -8920,7 +8920,7 @@
/**
* Registers remote animations per transition type for this activity.
*
- * @param definition The remote animation definition that defines which transition whould run
+ * @param definition The remote animation definition that defines which transition would run
* which remote animation.
* @hide
*/
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d328b34..9328664 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -231,6 +231,114 @@
final ArrayMap<OnUidImportanceListener, UidObserver> mImportanceListeners = new ArrayMap<>();
/**
+ * Callback object for {@link #registerUidFrozenStateChangedCallback}
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ public interface UidFrozenStateChangedCallback {
+ /**
+ * Indicates that the UID was frozen.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ int UID_FROZEN_STATE_FROZEN = 1;
+
+ /**
+ * Indicates that the UID was unfrozen.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ int UID_FROZEN_STATE_UNFROZEN = 2;
+
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = false, prefix = {"UID_FROZEN_STATE_"}, value = {
+ UID_FROZEN_STATE_FROZEN,
+ UID_FROZEN_STATE_UNFROZEN,
+ })
+ public @interface UidFrozenState {}
+
+ /**
+ * Notify the client that the frozen states of an array of UIDs have changed.
+ *
+ * @param uids The UIDs for which the frozen state has changed
+ * @param frozenStates Frozen state for each UID index, Will be set to
+ * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN}
+ * when the UID is frozen. When the UID is unfrozen,
+ * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN}
+ * will be set.
+ *
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ void onUidFrozenStateChanged(@NonNull int[] uids,
+ @NonNull @UidFrozenState int[] frozenStates);
+ }
+
+ /**
+ * Register a {@link UidFrozenStateChangedCallback} object to receive notification
+ * when a UID is frozen or unfrozen. Will throw an exception if the same
+ * callback object is registered more than once.
+ *
+ * @param executor The executor that the callback will be run from.
+ * @param callback The callback to be registered. Callbacks for previous frozen/unfrozen
+ * UID changes will not be delivered. Only changes in state from the point of
+ * registration onward will be reported.
+ * @throws IllegalStateException if the {@code callback} is already registered.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ public void registerUidFrozenStateChangedCallback(
+ @NonNull Executor executor,
+ @NonNull UidFrozenStateChangedCallback callback) {
+ }
+
+ /**
+ * Unregister a {@link UidFrozenStateChangedCallback} callback.
+ * @param callback The callback to be unregistered.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ public void unregisterUidFrozenStateChangedCallback(
+ @NonNull UidFrozenStateChangedCallback callback) {
+ }
+
+ /**
+ * Query the frozen state of a list of UIDs.
+ *
+ * @param uids the array of UIDs which the client would like to know the frozen state of.
+ * @return An array containing the frozen state for each requested UID, by index. Will be set
+ * to {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_FROZEN}
+ * if the UID is frozen. If the UID is not frozen or not found,
+ * {@link UidFrozenStateChangedCallback#UID_FROZEN_STATE_UNFROZEN}
+ * will be set.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
+ public @NonNull @UidFrozenStateChangedCallback.UidFrozenState
+ int[] getUidFrozenState(@NonNull int[] uids) {
+ return new int[uids.length];
+ }
+
+ /**
* <a href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code
* <meta-data>}</a> name for a 'home' Activity that declares a package that is to be
* uninstalled in lieu of the declaring one. The package named here must be
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5599893..a1e4dbf 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -238,6 +238,7 @@
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.net.InetAddress;
+import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
@@ -265,7 +266,6 @@
implements ActivityThreadInternal {
/** @hide */
public static final String TAG = "ActivityThread";
- private static final android.graphics.Bitmap.Config THUMBNAIL_FORMAT = Bitmap.Config.RGB_565;
static final boolean localLOGV = false;
static final boolean DEBUG_MESSAGES = false;
/** @hide */
@@ -367,7 +367,7 @@
private final AtomicInteger mNumLaunchingActivities = new AtomicInteger();
@GuardedBy("mAppThread")
private int mLastProcessState = PROCESS_STATE_UNKNOWN;
- ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
+ final ArrayList<WeakReference<AssistStructure>> mLastAssistStructures = new ArrayList<>();
private int mLastSessionId;
final ArrayMap<IBinder, CreateServiceData> mServicesData = new ArrayMap<>();
@UnsupportedAppUsage
@@ -563,7 +563,7 @@
Configuration createdConfig;
Configuration overrideConfig;
// Used for consolidating configs before sending on to Activity.
- private Configuration tmpConfig = new Configuration();
+ private final Configuration tmpConfig = new Configuration();
// Callback used for updating activity override config and camera compat control state.
ViewRootImpl.ActivityConfigCallback activityConfigCallback;
ActivityClientRecord nextIdle;
@@ -768,7 +768,7 @@
}
}
- final class ProviderClientRecord {
+ static final class ProviderClientRecord {
final String[] mNames;
@UnsupportedAppUsage
final IContentProvider mProvider;
@@ -795,7 +795,7 @@
}
@UnsupportedAppUsage
- Intent intent;
+ final Intent intent;
@UnsupportedAppUsage
ActivityInfo info;
@UnsupportedAppUsage
@@ -3335,11 +3335,8 @@
public void registerOnActivityPausedListener(Activity activity,
OnActivityPausedListener listener) {
synchronized (mOnPauseListeners) {
- ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
- if (list == null) {
- list = new ArrayList<OnActivityPausedListener>();
- mOnPauseListeners.put(activity, list);
- }
+ ArrayList<OnActivityPausedListener> list =
+ mOnPauseListeners.computeIfAbsent(activity, k -> new ArrayList<>());
list.add(listener);
}
}
@@ -4221,18 +4218,20 @@
static void handleAttachStartupAgents(String dataDir) {
try {
- Path code_cache = ContextImpl.getCodeCacheDirBeforeBind(new File(dataDir)).toPath();
- if (!Files.exists(code_cache)) {
+ Path codeCache = ContextImpl.getCodeCacheDirBeforeBind(new File(dataDir)).toPath();
+ if (!Files.exists(codeCache)) {
return;
}
- Path startup_path = code_cache.resolve("startup_agents");
- if (Files.exists(startup_path)) {
- for (Path p : Files.newDirectoryStream(startup_path)) {
- handleAttachAgent(
- p.toAbsolutePath().toString()
- + "="
- + dataDir,
- null);
+ Path startupPath = codeCache.resolve("startup_agents");
+ if (Files.exists(startupPath)) {
+ try (DirectoryStream<Path> startupFiles = Files.newDirectoryStream(startupPath)) {
+ for (Path p : startupFiles) {
+ handleAttachAgent(
+ p.toAbsolutePath().toString()
+ + "="
+ + dataDir,
+ null);
+ }
}
}
} catch (Exception e) {
@@ -5397,7 +5396,7 @@
/** Core implementation of activity destroy call. */
void performDestroyActivity(ActivityClientRecord r, boolean finishing,
int configChanges, boolean getNonConfigInstance, String reason) {
- Class<? extends Activity> activityClass = null;
+ Class<? extends Activity> activityClass;
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
activityClass = r.activity.getClass();
r.activity.mConfigChangeFlags |= configChanges;
@@ -7048,7 +7047,7 @@
// Note that we cannot hold the lock while acquiring and installing the
// provider since it might take a long time to run and it could also potentially
// be re-entrant in the case where the provider is in the same process.
- ContentProviderHolder holder = null;
+ ContentProviderHolder holder;
final ProviderKey key = getGetProviderKey(auth, userId);
try {
synchronized (key) {
@@ -7102,11 +7101,7 @@
private ProviderKey getGetProviderKey(String auth, int userId) {
final ProviderKey key = new ProviderKey(auth, userId);
synchronized (mGetProviderKeys) {
- ProviderKey lock = mGetProviderKeys.get(key);
- if (lock == null) {
- lock = key;
- mGetProviderKeys.put(key, lock);
- }
+ ProviderKey lock = mGetProviderKeys.computeIfAbsent(key, k -> k);
return lock;
}
}
@@ -7741,7 +7736,7 @@
if (!DEPRECATE_DATA_COLUMNS) return;
// Install interception and make sure it sticks!
- Os def = null;
+ Os def;
do {
def = Os.getDefault();
} while (!Os.compareAndSetDefault(def, new AndroidOs(def)));
diff --git a/core/java/android/app/AliasActivity.java b/core/java/android/app/AliasActivity.java
index 37be901..f266769 100644
--- a/core/java/android/app/AliasActivity.java
+++ b/core/java/android/app/AliasActivity.java
@@ -16,9 +16,6 @@
package android.app;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -29,13 +26,16 @@
import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
/**
* Stub activity that launches another activity (and then finishes itself)
* based on information in its component's manifest meta-data. This is a
* simple way to implement an alias-like mechanism.
- *
+ *
* To use this activity, you should include in the manifest for the associated
* component an entry named "android.app.alias". It is a reference to an XML
* resource describing an intent that launches the real application.
@@ -51,11 +51,11 @@
* {@hide}
*/
public final String ALIAS_META_DATA = "android.app.alias";
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
XmlResourceParser parser = null;
try {
ActivityInfo ai = getPackageManager().getActivityInfo(
@@ -66,21 +66,17 @@
throw new RuntimeException("Alias requires a meta-data field "
+ ALIAS_META_DATA);
}
-
+
Intent intent = parseAlias(parser);
if (intent == null) {
throw new RuntimeException(
"No <intent> tag found in alias description");
}
-
+
startActivity(intent);
finish();
-
- } catch (PackageManager.NameNotFoundException e) {
- throw new RuntimeException("Error parsing alias", e);
- } catch (XmlPullParserException e) {
- throw new RuntimeException("Error parsing alias", e);
- } catch (IOException e) {
+
+ } catch (PackageManager.NameNotFoundException | XmlPullParserException | IOException e) {
throw new RuntimeException("Error parsing alias", e);
} finally {
if (parser != null) parser.close();
@@ -90,21 +86,21 @@
private Intent parseAlias(XmlPullParser parser)
throws XmlPullParserException, IOException {
AttributeSet attrs = Xml.asAttributeSet(parser);
-
+
Intent intent = null;
-
+
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
}
-
+
String nodeName = parser.getName();
if (!"alias".equals(nodeName)) {
throw new RuntimeException(
"Alias meta-data must start with <alias> tag; found"
+ nodeName + " at " + parser.getPositionDescription());
}
-
+
int outerDepth = parser.getDepth();
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -120,8 +116,8 @@
XmlUtils.skipCurrentTag(parser);
}
}
-
+
return intent;
}
-
+
}
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index bccbb38..2a854b2 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -37,8 +37,6 @@
import android.os.PowerExemptionManager.ReasonCode;
import android.os.PowerExemptionManager.TempAllowListType;
-import com.android.internal.util.Preconditions;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
@@ -61,7 +59,8 @@
private long mRequireCompatChangeId = CHANGE_INVALID;
private long mIdForResponseEvent;
private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
- private @Nullable String mDeliveryGroupMatchingKey;
+ private @Nullable String mDeliveryGroupMatchingNamespaceFragment;
+ private @Nullable String mDeliveryGroupMatchingKeyFragment;
private @Nullable BundleMerger mDeliveryGroupExtrasMerger;
private @Nullable IntentFilter mDeliveryGroupMatchingFilter;
private @DeferralPolicy int mDeferralPolicy;
@@ -209,7 +208,13 @@
"android:broadcast.deliveryGroupPolicy";
/**
- * Corresponds to {@link #setDeliveryGroupMatchingKey(String, String)}.
+ * Corresponds to namespace fragment of {@link #setDeliveryGroupMatchingKey(String, String)}.
+ */
+ private static final String KEY_DELIVERY_GROUP_NAMESPACE =
+ "android:broadcast.deliveryGroupMatchingNamespace";
+
+ /**
+ * Corresponds to key fragment of {@link #setDeliveryGroupMatchingKey(String, String)}.
*/
private static final String KEY_DELIVERY_GROUP_KEY =
"android:broadcast.deliveryGroupMatchingKey";
@@ -350,7 +355,8 @@
mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY,
DELIVERY_GROUP_POLICY_ALL);
- mDeliveryGroupMatchingKey = opts.getString(KEY_DELIVERY_GROUP_KEY);
+ mDeliveryGroupMatchingNamespaceFragment = opts.getString(KEY_DELIVERY_GROUP_NAMESPACE);
+ mDeliveryGroupMatchingKeyFragment = opts.getString(KEY_DELIVERY_GROUP_KEY);
mDeliveryGroupExtrasMerger = opts.getParcelable(KEY_DELIVERY_GROUP_EXTRAS_MERGER,
BundleMerger.class);
mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER,
@@ -864,11 +870,8 @@
@NonNull
public BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String namespace,
@NonNull String key) {
- Preconditions.checkArgument(!namespace.contains(":"),
- "namespace should not contain ':'");
- Preconditions.checkArgument(!key.contains(":"),
- "key should not contain ':'");
- mDeliveryGroupMatchingKey = namespace + ":" + key;
+ mDeliveryGroupMatchingNamespaceFragment = Objects.requireNonNull(namespace);
+ mDeliveryGroupMatchingKeyFragment = Objects.requireNonNull(key);
return this;
}
@@ -881,7 +884,38 @@
*/
@Nullable
public String getDeliveryGroupMatchingKey() {
- return mDeliveryGroupMatchingKey;
+ if (mDeliveryGroupMatchingNamespaceFragment == null
+ || mDeliveryGroupMatchingKeyFragment == null) {
+ return null;
+ }
+ return String.join(":", mDeliveryGroupMatchingNamespaceFragment,
+ mDeliveryGroupMatchingKeyFragment);
+ }
+
+ /**
+ * Return the namespace fragment that is used to identify the delivery group that this
+ * broadcast belongs to.
+ *
+ * @return the delivery group namespace fragment that was previously set using
+ * {@link #setDeliveryGroupMatchingKey(String, String)}.
+ * @hide
+ */
+ @Nullable
+ public String getDeliveryGroupMatchingNamespaceFragment() {
+ return mDeliveryGroupMatchingNamespaceFragment;
+ }
+
+ /**
+ * Return the key fragment that is used to identify the delivery group that this
+ * broadcast belongs to.
+ *
+ * @return the delivery group key fragment that was previously set using
+ * {@link #setDeliveryGroupMatchingKey(String, String)}.
+ * @hide
+ */
+ @Nullable
+ public String getDeliveryGroupMatchingKeyFragment() {
+ return mDeliveryGroupMatchingKeyFragment;
}
/**
@@ -889,7 +923,8 @@
* {@link #setDeliveryGroupMatchingKey(String, String)}.
*/
public void clearDeliveryGroupMatchingKey() {
- mDeliveryGroupMatchingKey = null;
+ mDeliveryGroupMatchingNamespaceFragment = null;
+ mDeliveryGroupMatchingKeyFragment = null;
}
/**
@@ -1101,8 +1136,11 @@
if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) {
b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy);
}
- if (mDeliveryGroupMatchingKey != null) {
- b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKey);
+ if (mDeliveryGroupMatchingNamespaceFragment != null) {
+ b.putString(KEY_DELIVERY_GROUP_NAMESPACE, mDeliveryGroupMatchingNamespaceFragment);
+ }
+ if (mDeliveryGroupMatchingKeyFragment != null) {
+ b.putString(KEY_DELIVERY_GROUP_KEY, mDeliveryGroupMatchingKeyFragment);
}
if (mDeliveryGroupPolicy == DELIVERY_GROUP_POLICY_MERGED) {
if (mDeliveryGroupExtrasMerger != null) {
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index bd5d105..05742e6 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -535,7 +535,7 @@
*/
public static SearchableInfo getActivityMetaData(Context context, ActivityInfo activityInfo,
int userId) {
- Context userContext = null;
+ Context userContext;
try {
userContext = context.createPackageContextAsUser("system", 0,
new UserHandle(userId));
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index 99d4064..e563de2 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -96,31 +96,30 @@
throws XmlPullParserException, IOException {
mService = service;
ServiceInfo si = service.serviceInfo;
-
+
final PackageManager pm = context.getPackageManager();
- XmlResourceParser parser = null;
- try {
- parser = si.loadXmlMetaData(pm, WallpaperService.SERVICE_META_DATA);
+ try (XmlResourceParser parser = si.loadXmlMetaData(pm,
+ WallpaperService.SERVICE_META_DATA)) {
if (parser == null) {
throw new XmlPullParserException("No "
+ WallpaperService.SERVICE_META_DATA + " meta-data");
}
-
+
Resources res = pm.getResourcesForApplication(si.applicationInfo);
-
+
AttributeSet attrs = Xml.asAttributeSet(parser);
-
+
int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& type != XmlPullParser.START_TAG) {
}
-
+
String nodeName = parser.getName();
if (!"wallpaper".equals(nodeName)) {
throw new XmlPullParserException(
"Meta-data does not start with wallpaper tag");
}
-
+
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.Wallpaper);
mSettingsActivityName = sa.getString(
@@ -159,8 +158,6 @@
} catch (NameNotFoundException e) {
throw new XmlPullParserException(
"Unable to create context for: " + si.packageName);
- } finally {
- if (parser != null) parser.close();
}
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index dea1a05..75b450d 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1629,7 +1629,6 @@
mContext.getUserId());
if (fd != null) {
FileOutputStream fos = null;
- boolean ok = false;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
diff --git a/core/java/android/app/assist/OWNERS b/core/java/android/app/assist/OWNERS
index e857c72..e4ffd7f 100644
--- a/core/java/android/app/assist/OWNERS
+++ b/core/java/android/app/assist/OWNERS
@@ -1,5 +1,2 @@
-augale@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
-tymtsai@google.com
+hackz@google.com
+volnov@google.com
\ No newline at end of file
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2ea0d82..a320f1e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -11488,7 +11488,7 @@
private void toUriInner(StringBuilder uri, String scheme, String defAction,
String defPackage, int flags) {
if (scheme != null) {
- uri.append("scheme=").append(scheme).append(';');
+ uri.append("scheme=").append(Uri.encode(scheme)).append(';');
}
if (mAction != null && !mAction.equals(defAction)) {
uri.append("action=").append(Uri.encode(mAction)).append(';');
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index b1252fd..49d3cac 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.PendingIntentInfo;
+import android.app.ActivityOptions;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Handler;
@@ -158,7 +159,7 @@
*/
public void sendIntent(Context context, int code, Intent intent,
OnFinished onFinished, Handler handler) throws SendIntentException {
- sendIntent(context, code, intent, onFinished, handler, null);
+ sendIntent(context, code, intent, onFinished, handler, null, null /* options */);
}
/**
@@ -190,6 +191,42 @@
public void sendIntent(Context context, int code, Intent intent,
OnFinished onFinished, Handler handler, String requiredPermission)
throws SendIntentException {
+ sendIntent(context, code, intent, onFinished, handler, requiredPermission,
+ null /* options */);
+ }
+
+ /**
+ * Perform the operation associated with this IntentSender, allowing the
+ * caller to specify information about the Intent to use and be notified
+ * when the send has completed.
+ *
+ * @param context The Context of the caller. This may be null if
+ * <var>intent</var> is also null.
+ * @param code Result code to supply back to the IntentSender's target.
+ * @param intent Additional Intent data. See {@link Intent#fillIn
+ * Intent.fillIn()} for information on how this is applied to the
+ * original Intent. Use null to not modify the original Intent.
+ * @param onFinished The object to call back on when the send has
+ * completed, or null for no callback.
+ * @param handler Handler identifying the thread on which the callback
+ * should happen. If null, the callback will happen from the thread
+ * pool of the process.
+ * @param requiredPermission Name of permission that a recipient of the PendingIntent
+ * is required to hold. This is only valid for broadcast intents, and
+ * corresponds to the permission argument in
+ * {@link Context#sendBroadcast(Intent, String) Context.sendOrderedBroadcast(Intent, String)}.
+ * If null, no permission is required.
+ * @param options Additional options the caller would like to provide to modify the sending
+ * behavior. May be built from an {@link ActivityOptions} to apply to an activity start.
+ *
+ * @throws SendIntentException Throws CanceledIntentException if the IntentSender
+ * is no longer allowing more intents to be sent through it.
+ * @hide
+ */
+ public void sendIntent(Context context, int code, Intent intent,
+ OnFinished onFinished, Handler handler, String requiredPermission,
+ @Nullable Bundle options)
+ throws SendIntentException {
try {
String resolvedType = intent != null ?
intent.resolveTypeIfNeeded(context.getContentResolver())
@@ -199,7 +236,7 @@
onFinished != null
? new FinishedDispatcher(this, onFinished, handler)
: null,
- requiredPermission, null);
+ requiredPermission, options);
if (res < 0) {
throw new SendIntentException();
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index a6c79b3..9179f5d 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -2228,6 +2228,12 @@
} else {
List<CaptureResult> partialResults =
mFrameNumberTracker.popPartialResults(frameNumber);
+ if (mBatchOutputMap.containsKey(requestId)) {
+ int requestCount = mBatchOutputMap.get(requestId);
+ for (int i = 1; i < requestCount; i++) {
+ mFrameNumberTracker.popPartialResults(frameNumber - (requestCount - i));
+ }
+ }
final long sensorTimestamp =
result.get(CaptureResult.SENSOR_TIMESTAMP);
diff --git a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
index aee20db..e977751 100644
--- a/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
+++ b/core/java/android/hardware/camera2/impl/CameraExtensionJpegProcessor.java
@@ -46,6 +46,7 @@
public class CameraExtensionJpegProcessor implements ICaptureProcessorImpl {
public final static String TAG = "CameraExtensionJpeg";
private final static int JPEG_QUEUE_SIZE = 1;
+ private final static int JPEG_APP_SEGMENT_SIZE = 64 * 1024;
private final Handler mHandler;
private final HandlerThread mHandlerThread;
@@ -225,9 +226,10 @@
private void initializePipeline() throws RemoteException {
if ((mFormat != -1) && (mOutputSurface != null) && (mResolution != null) &&
(mYuvReader == null)) {
- // Jpeg/blobs are expected to be configured with (w*h)x1
+ // Jpeg/blobs are expected to be configured with (w*h)x1.5 + 64k Jpeg APP1 segment
mOutputWriter = ImageWriter.newInstance(mOutputSurface, 1 /*maxImages*/,
- ImageFormat.JPEG, mResolution.width * mResolution.height, 1);
+ ImageFormat.JPEG,
+ (mResolution.width * mResolution.height * 3)/2 + JPEG_APP_SEGMENT_SIZE, 1);
mYuvReader = ImageReader.newInstance(mResolution.width, mResolution.height, mFormat,
JPEG_QUEUE_SIZE);
mYuvReader.setOnImageAvailableListener(new YuvCallback(), mHandler);
diff --git a/core/java/android/hardware/soundtrigger/OWNERS b/core/java/android/hardware/soundtrigger/OWNERS
index 01b2cb9..1e41886 100644
--- a/core/java/android/hardware/soundtrigger/OWNERS
+++ b/core/java/android/hardware/soundtrigger/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index 7c2e518..44144d9 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -238,7 +238,7 @@
* or negative value for failure
*/
public int controlTransfer(int requestType, int request, int value,
- int index, byte[] buffer, int length, int timeout) {
+ int index, @Nullable byte[] buffer, int length, int timeout) {
return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout);
}
@@ -263,7 +263,7 @@
* or negative value for failure
*/
public int controlTransfer(int requestType, int request, int value, int index,
- byte[] buffer, int offset, int length, int timeout) {
+ @Nullable byte[] buffer, int offset, int length, int timeout) {
checkBounds(buffer, offset, length);
return native_control_request(requestType, request, value, index,
buffer, offset, length, timeout);
diff --git a/core/java/android/net/metrics/WakeupStats.java b/core/java/android/net/metrics/WakeupStats.java
index bb36536..fac747c 100644
--- a/core/java/android/net/metrics/WakeupStats.java
+++ b/core/java/android/net/metrics/WakeupStats.java
@@ -80,18 +80,20 @@
break;
}
- switch (ev.dstHwAddr.getAddressType()) {
- case MacAddress.TYPE_UNICAST:
- l2UnicastCount++;
- break;
- case MacAddress.TYPE_MULTICAST:
- l2MulticastCount++;
- break;
- case MacAddress.TYPE_BROADCAST:
- l2BroadcastCount++;
- break;
- default:
- break;
+ if (ev.dstHwAddr != null) {
+ switch (ev.dstHwAddr.getAddressType()) {
+ case MacAddress.TYPE_UNICAST:
+ l2UnicastCount++;
+ break;
+ case MacAddress.TYPE_MULTICAST:
+ l2MulticastCount++;
+ break;
+ case MacAddress.TYPE_BROADCAST:
+ l2BroadcastCount++;
+ break;
+ default:
+ break;
+ }
}
increment(ethertypes, ev.ethertype);
diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
index 38b3174..46cf016 100644
--- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
@@ -354,6 +354,7 @@
}
/** @hide */
+ @Override
public Map<Integer, Integer> getCapabilitiesMatchCriteria() {
return Collections.unmodifiableMap(new HashMap<>(mCapabilitiesMatchCriteria));
}
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index 6f9c9dd..a27e923 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -16,6 +16,7 @@
package android.net.vcn;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
@@ -75,6 +76,7 @@
static {
ALLOWED_TRANSPORTS.add(TRANSPORT_WIFI);
ALLOWED_TRANSPORTS.add(TRANSPORT_CELLULAR);
+ ALLOWED_TRANSPORTS.add(TRANSPORT_TEST);
}
private static final String PACKAGE_NAME_KEY = "mPackageName";
@@ -155,6 +157,11 @@
+ transport
+ " which might be from a new version of VcnConfig");
}
+
+ if (transport == TRANSPORT_TEST && !mIsTestModeProfile) {
+ throw new IllegalArgumentException(
+ "Found TRANSPORT_TEST in a non-test-mode profile");
+ }
}
}
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
index 9235d09..edf2c09 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
@@ -29,6 +29,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Map;
import java.util.Objects;
/**
@@ -307,4 +308,7 @@
public int getMinExitDownstreamBandwidthKbps() {
return mMinExitDownstreamBandwidthKbps;
}
+
+ /** @hide */
+ public abstract Map<Integer, Integer> getCapabilitiesMatchCriteria();
}
diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
index 2544a6d..2e6b09f 100644
--- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
@@ -15,6 +15,9 @@
*/
package android.net.vcn;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
+
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER;
@@ -23,6 +26,7 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.net.NetworkCapabilities;
+import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria;
import android.os.PersistableBundle;
import android.util.ArraySet;
@@ -32,6 +36,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -162,6 +167,12 @@
return Collections.unmodifiableSet(mSsids);
}
+ /** @hide */
+ @Override
+ public Map<Integer, Integer> getCapabilitiesMatchCriteria() {
+ return Collections.singletonMap(NET_CAPABILITY_INTERNET, MATCH_REQUIRED);
+ }
+
/** This class is used to incrementally build VcnWifiUnderlyingNetworkTemplate objects. */
public static final class Builder {
private int mMeteredMatchCriteria = MATCH_ANY;
diff --git a/core/java/android/nfc/NfcAntennaInfo.java b/core/java/android/nfc/NfcAntennaInfo.java
index d54fcd2..b002ca2 100644
--- a/core/java/android/nfc/NfcAntennaInfo.java
+++ b/core/java/android/nfc/NfcAntennaInfo.java
@@ -85,8 +85,8 @@
this.mDeviceHeight = in.readInt();
this.mDeviceFoldable = in.readByte() != 0;
this.mAvailableNfcAntennas = new ArrayList<>();
- in.readParcelableList(this.mAvailableNfcAntennas,
- AvailableNfcAntenna.class.getClassLoader());
+ in.readTypedList(this.mAvailableNfcAntennas,
+ AvailableNfcAntenna.CREATOR);
}
public static final @NonNull Parcelable.Creator<NfcAntennaInfo> CREATOR =
diff --git a/core/java/android/nfc/tech/NdefFormatable.java b/core/java/android/nfc/tech/NdefFormatable.java
index f19d302..2240fe7 100644
--- a/core/java/android/nfc/tech/NdefFormatable.java
+++ b/core/java/android/nfc/tech/NdefFormatable.java
@@ -124,6 +124,9 @@
try {
int serviceHandle = mTag.getServiceHandle();
INfcTag tagService = mTag.getTagService();
+ if (tagService == null) {
+ throw new IOException();
+ }
int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT);
switch (errorCode) {
case ErrorCodes.SUCCESS:
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 0cb7df7..5d0a723 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -325,7 +325,24 @@
* @hide
*/
@CriticalNative
- public static final native boolean isDirectlyHandlingTransaction();
+ public static final native boolean isDirectlyHandlingTransactionNative();
+
+ private static boolean sIsHandlingBinderTransaction = false;
+
+ /**
+ * @hide
+ */
+ public static final boolean isDirectlyHandlingTransaction() {
+ return sIsHandlingBinderTransaction || isDirectlyHandlingTransactionNative();
+ }
+
+ /**
+ * This is Test API which will be used to override output of isDirectlyHandlingTransactionNative
+ * @hide
+ */
+ public static void setIsDirectlyHandlingTransactionOverride(boolean isInTransaction) {
+ sIsHandlingBinderTransaction = isInTransaction;
+ }
/**
* Returns {@code true} if the current thread has had its identity
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 244632a..2e05b8d 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1223,6 +1223,11 @@
* Upside Down Cake.
*/
public static final int UPSIDE_DOWN_CAKE = CUR_DEVELOPMENT;
+
+ /**
+ * Vanilla Ice Cream.
+ */
+ public static final int VANILLA_ICE_CREAM = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 0f5fc34..cdc8268 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -63,6 +63,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -363,6 +364,22 @@
// see libbinder's binder/Status.h
private static final int EX_TRANSACTION_FAILED = -129;
+ // Allow limit of 1 MB for allocating arrays
+ private static final int ARRAY_ALLOCATION_LIMIT = 1000000;
+
+ // Following type size are used to determine allocation size while creating arrays
+ private static final int SIZE_BYTE = 1;
+ private static final int SIZE_CHAR = 2;
+ private static final int SIZE_SHORT = 2;
+ private static final int SIZE_BOOLEAN = 4;
+ private static final int SIZE_INT = 4;
+ private static final int SIZE_FLOAT = 4;
+ private static final int SIZE_DOUBLE = 8;
+ private static final int SIZE_LONG = 8;
+
+ // Assume the least possible size for complex objects
+ private static final int SIZE_COMPLEX_TYPE = 1;
+
@CriticalNative
private static native void nativeMarkSensitive(long nativePtr);
@FastNative
@@ -1503,9 +1520,71 @@
}
}
+ private static <T> int getItemTypeSize(@NonNull Class<T> arrayClass) {
+ final Class<?> componentType = arrayClass.getComponentType();
+ // typeSize has been referred from respective create*Array functions
+ if (componentType == boolean.class) {
+ return SIZE_BOOLEAN;
+ } else if (componentType == byte.class) {
+ return SIZE_BYTE;
+ } else if (componentType == char.class) {
+ return SIZE_CHAR;
+ } else if (componentType == int.class) {
+ return SIZE_INT;
+ } else if (componentType == long.class) {
+ return SIZE_LONG;
+ } else if (componentType == float.class) {
+ return SIZE_FLOAT;
+ } else if (componentType == double.class) {
+ return SIZE_DOUBLE;
+ }
+
+ return SIZE_COMPLEX_TYPE;
+ }
+
+ private void ensureWithinMemoryLimit(int typeSize, @NonNull int... dimensions) {
+ // For Multidimensional arrays, Calculate total object
+ // which will be allocated.
+ int totalObjects = 1;
+ try {
+ for (int dimension : dimensions) {
+ totalObjects = Math.multiplyExact(totalObjects, dimension);
+ }
+ } catch (ArithmeticException e) {
+ Log.e(TAG, "ArithmeticException occurred while multiplying dimensions " + e);
+ BadParcelableException badParcelableException = new BadParcelableException("Estimated "
+ + "array length is too large. Array Dimensions:" + Arrays.toString(dimensions));
+ SneakyThrow.sneakyThrow(badParcelableException);
+ }
+ ensureWithinMemoryLimit(typeSize, totalObjects);
+ }
+
+ private void ensureWithinMemoryLimit(int typeSize, @NonNull int length) {
+ int estimatedAllocationSize = 0;
+ try {
+ estimatedAllocationSize = Math.multiplyExact(typeSize, length);
+ } catch (ArithmeticException e) {
+ Log.e(TAG, "ArithmeticException occurred while multiplying values " + typeSize
+ + " and " + length + " Exception: " + e);
+ BadParcelableException badParcelableException = new BadParcelableException("Estimated "
+ + "allocation size is too large. typeSize: " + typeSize + " length: " + length);
+ SneakyThrow.sneakyThrow(badParcelableException);
+ }
+
+ boolean isInBinderTransaction = Binder.isDirectlyHandlingTransaction();
+ if (isInBinderTransaction && (estimatedAllocationSize > ARRAY_ALLOCATION_LIMIT)) {
+ Log.e(TAG, "Trying to Allocate " + estimatedAllocationSize
+ + " memory, In Binder Transaction : " + isInBinderTransaction);
+ BadParcelableException e = new BadParcelableException("Allocation of size "
+ + estimatedAllocationSize + " is above allowed limit of 1MB");
+ SneakyThrow.sneakyThrow(e);
+ }
+ }
+
@Nullable
public final boolean[] createBooleanArray() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_BOOLEAN, N);
// >>2 as a fast divide-by-4 works in the create*Array() functions
// because dataAvail() will never return a negative number. 4 is
// the size of a stored boolean in the stream.
@@ -1548,6 +1627,7 @@
@Nullable
public short[] createShortArray() {
int n = readInt();
+ ensureWithinMemoryLimit(SIZE_SHORT, n);
if (n >= 0 && n <= (dataAvail() >> 2)) {
short[] val = new short[n];
for (int i = 0; i < n; i++) {
@@ -1586,6 +1666,7 @@
@Nullable
public final char[] createCharArray() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_CHAR, N);
if (N >= 0 && N <= (dataAvail() >> 2)) {
char[] val = new char[N];
for (int i=0; i<N; i++) {
@@ -1623,6 +1704,7 @@
@Nullable
public final int[] createIntArray() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_INT, N);
if (N >= 0 && N <= (dataAvail() >> 2)) {
int[] val = new int[N];
for (int i=0; i<N; i++) {
@@ -1660,6 +1742,7 @@
@Nullable
public final long[] createLongArray() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_LONG, N);
// >>3 because stored longs are 64 bits
if (N >= 0 && N <= (dataAvail() >> 3)) {
long[] val = new long[N];
@@ -1698,6 +1781,7 @@
@Nullable
public final float[] createFloatArray() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_FLOAT, N);
// >>2 because stored floats are 4 bytes
if (N >= 0 && N <= (dataAvail() >> 2)) {
float[] val = new float[N];
@@ -1736,6 +1820,7 @@
@Nullable
public final double[] createDoubleArray() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_DOUBLE, N);
// >>3 because stored doubles are 8 bytes
if (N >= 0 && N <= (dataAvail() >> 3)) {
double[] val = new double[N];
@@ -1789,6 +1874,7 @@
@Nullable
public final String[] createString8Array() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
if (N >= 0) {
String[] val = new String[N];
for (int i=0; i<N; i++) {
@@ -1829,6 +1915,7 @@
@Nullable
public final String[] createString16Array() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
if (N >= 0) {
String[] val = new String[N];
for (int i=0; i<N; i++) {
@@ -1921,6 +2008,7 @@
@Nullable
public final IBinder[] createBinderArray() {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
if (N >= 0) {
IBinder[] val = new IBinder[N];
for (int i=0; i<N; i++) {
@@ -1955,6 +2043,7 @@
public final <T extends IInterface> T[] createInterfaceArray(
@NonNull IntFunction<T[]> newArray, @NonNull Function<IBinder, T> asInterface) {
int N = readInt();
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
if (N >= 0) {
T[] val = newArray.apply(N);
for (int i=0; i<N; i++) {
@@ -3201,6 +3290,7 @@
if (N < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
FileDescriptor[] f = new FileDescriptor[N];
for (int i = 0; i < N; i++) {
f[i] = readRawFileDescriptor();
@@ -3667,6 +3757,7 @@
if (N < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
ArrayList<T> l = new ArrayList<T>(N);
while (N > 0) {
l.add(readTypedObject(c));
@@ -3721,6 +3812,7 @@
if (count < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count);
final SparseArray<T> array = new SparseArray<>(count);
for (int i = 0; i < count; i++) {
final int index = readInt();
@@ -3749,6 +3841,7 @@
if (count < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, count);
final ArrayMap<String, T> map = new ArrayMap<>(count);
for (int i = 0; i < count; i++) {
final String key = readString();
@@ -3775,6 +3868,7 @@
if (N < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
ArrayList<String> l = new ArrayList<String>(N);
while (N > 0) {
l.add(readString());
@@ -3800,6 +3894,7 @@
if (N < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
ArrayList<IBinder> l = new ArrayList<IBinder>(N);
while (N > 0) {
l.add(readStrongBinder());
@@ -3826,6 +3921,7 @@
if (N < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
ArrayList<T> l = new ArrayList<T>(N);
while (N > 0) {
l.add(asInterface.apply(readStrongBinder()));
@@ -3985,6 +4081,7 @@
if (N < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, N);
T[] l = c.newArray(N);
for (int i=0; i<N; i++) {
l[i] = readTypedObject(c);
@@ -4213,6 +4310,10 @@
while (innermost.isArray()) {
innermost = innermost.getComponentType();
}
+
+ int typeSize = getItemTypeSize(innermost);
+ ensureWithinMemoryLimit(typeSize, dimensions);
+
val = (T) Array.newInstance(innermost, dimensions);
for (int i = 0; i < length; i++) {
readFixedArray(Array.get(val, i));
@@ -4269,6 +4370,10 @@
while (innermost.isArray()) {
innermost = innermost.getComponentType();
}
+
+ int typeSize = getItemTypeSize(innermost);
+ ensureWithinMemoryLimit(typeSize, dimensions);
+
val = (T) Array.newInstance(innermost, dimensions);
for (int i = 0; i < length; i++) {
readFixedArray(Array.get(val, i), asInterface);
@@ -4324,6 +4429,10 @@
while (innermost.isArray()) {
innermost = innermost.getComponentType();
}
+
+ int typeSize = getItemTypeSize(innermost);
+ ensureWithinMemoryLimit(typeSize, dimensions);
+
val = (T) Array.newInstance(innermost, dimensions);
for (int i = 0; i < length; i++) {
readFixedArray(Array.get(val, i), c);
@@ -5069,6 +5178,7 @@
if (n < 0) {
return null;
}
+ ensureWithinMemoryLimit(SIZE_COMPLEX_TYPE, 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);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index bb74e19..89da45b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1360,7 +1360,7 @@
String formatSize = MemoryProperties.memory_ddr_size().orElse("0KB");
long memSize = FileUtils.parseSize(formatSize);
- if (memSize == Long.MIN_VALUE) {
+ if (memSize <= 0) {
return FileUtils.roundStorageSize(getTotalMemory());
}
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 5aa4e27..7cdaecd 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -202,6 +202,13 @@
public static final String ACTION_NOTIFY_IF_IN_USE =
"android.os.image.action.NOTIFY_IF_IN_USE";
+ /**
+ * Intent action: hide notifications about the status of {@code DynamicSystem}.
+ * @hide
+ */
+ public static final String ACTION_HIDE_NOTIFICATION =
+ "android.os.image.action.HIDE_NOTIFICATION";
+
/*
* Intent Keys
*/
@@ -217,6 +224,28 @@
*/
public static final String KEY_USERDATA_SIZE = "KEY_USERDATA_SIZE";
+ /**
+ * Intent key: Whether to enable DynamicSystem immediately after installation is done.
+ * Note this will reboot the device automatically.
+ * @hide
+ */
+ public static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED";
+
+ /**
+ * Intent key: Whether to leave DynamicSystem on device reboot.
+ * False indicates a sticky mode where device stays in DynamicSystem across reboots.
+ * @hide
+ */
+ public static final String KEY_ONE_SHOT = "KEY_ONE_SHOT";
+
+ /**
+ * Intent key: Whether to use default strings when showing the dialog that prompts
+ * user for device credentials.
+ * False indicates using the custom strings provided by {@code DynamicSystem}.
+ * @hide
+ */
+ public static final String KEY_KEYGUARD_USE_DEFAULT_STRINGS =
+ "KEY_KEYGUARD_USE_DEFAULT_STRINGS";
private static class IncomingHandler extends Handler {
private final WeakReference<DynamicSystemClient> mWeakClient;
diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS
index d34b45b..4603e43f 100644
--- a/core/java/android/permission/OWNERS
+++ b/core/java/android/permission/OWNERS
@@ -1,18 +1,19 @@
# Bug component: 137825
-evanseverson@google.com
-evanxinchen@google.com
ashfall@google.com
-guojing@google.com
+augale@google.com
+evanseverson@google.com
+fayey@google.com
jaysullivan@google.com
+joecastro@google.com
kvakil@google.com
mrulhania@google.com
narayan@google.com
ntmyren@google.com
olekarg@google.com
pyuli@google.com
-raphk@google.com
rmacgregor@google.com
sergeynv@google.com
theianchen@google.com
+yutingfang@google.com
zhanghai@google.com
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 3c1b4ba..0012572 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8410,7 +8410,7 @@
extras.putString(KEY_ACCOUNT_NAME, accountName);
extras.putString(KEY_ACCOUNT_TYPE, accountType);
- contentResolver.call(ContactsContract.AUTHORITY_URI,
+ nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI,
ContactsContract.SimContacts.ADD_SIM_ACCOUNT_METHOD,
null, extras);
}
@@ -8433,7 +8433,7 @@
Bundle extras = new Bundle();
extras.putInt(KEY_SIM_SLOT_INDEX, simSlotIndex);
- contentResolver.call(ContactsContract.AUTHORITY_URI,
+ nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI,
ContactsContract.SimContacts.REMOVE_SIM_ACCOUNT_METHOD,
null, extras);
}
@@ -8445,7 +8445,7 @@
*/
public static @NonNull List<SimAccount> getSimAccounts(
@NonNull ContentResolver contentResolver) {
- Bundle response = contentResolver.call(ContactsContract.AUTHORITY_URI,
+ Bundle response = nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI,
ContactsContract.SimContacts.QUERY_SIM_ACCOUNTS_METHOD,
null, null);
List<SimAccount> result = response.getParcelableArrayList(KEY_SIM_ACCOUNTS);
@@ -9064,7 +9064,8 @@
* @param contactId the id of the contact to undemote.
*/
public static void undemote(ContentResolver contentResolver, long contactId) {
- contentResolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD,
+ nullSafeCall(contentResolver, ContactsContract.AUTHORITY_URI,
+ PinnedPositions.UNDEMOTE_METHOD,
String.valueOf(contactId), null);
}
@@ -10276,4 +10277,13 @@
public static final String CONTENT_ITEM_TYPE =
"vnd.android.cursor.item/contact_metadata_sync_state";
}
+
+ private static Bundle nullSafeCall(@NonNull ContentResolver resolver, @NonNull Uri uri,
+ @NonNull String method, @Nullable String arg, @Nullable Bundle extras) {
+ try (ContentProviderClient client = resolver.acquireContentProviderClient(uri)) {
+ return client.call(method, arg, extras);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 3dc805e..bb76b469 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4842,6 +4842,14 @@
*/
public static final String COLUMN_USER_HANDLE = "user_handle";
+ /**
+ * TelephonyProvider column name for satellite enabled.
+ * By default, it's disabled.
+ *
+ * @hide
+ */
+ public static final String COLUMN_SATELLITE_ENABLED = "satellite_enabled";
+
/** All columns in {@link SimInfo} table. */
private static final List<String> ALL_COLUMNS = List.of(
COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID,
@@ -4910,7 +4918,8 @@
COLUMN_PORT_INDEX,
COLUMN_USAGE_SETTING,
COLUMN_TP_MESSAGE_REF,
- COLUMN_USER_HANDLE
+ COLUMN_USER_HANDLE,
+ COLUMN_SATELLITE_ENABLED
);
/**
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 4d6422c..9088a77 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -337,8 +337,22 @@
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_PROOF_OF_PRESENCE_REQUIRED =
+ ErrorCode.PROOF_OF_PRESENCE_REQUIRED; // -69;
+ public static final int KM_ERROR_CONCURRENT_PROOF_OF_PRESENCE_REQUESTED =
+ ErrorCode.CONCURRENT_PROOF_OF_PRESENCE_REQUESTED; // -70;
+ public static final int KM_ERROR_NO_USER_CONFIRMATION =
+ ErrorCode.NO_USER_CONFIRMATION; // -71;
public static final int KM_ERROR_DEVICE_LOCKED =
ErrorCode.DEVICE_LOCKED; // -72;
+ public static final int KM_ERROR_EARLY_BOOT_ENDED =
+ ErrorCode.EARLY_BOOT_ENDED; // -73;
+ public static final int KM_ERROR_ATTESTATION_KEYS_NOT_PROVISIONED =
+ ErrorCode.ATTESTATION_KEYS_NOT_PROVISIONED; // -74;
+ public static final int KM_ERROR_ATTESTATION_IDS_NOT_PROVISIONED =
+ ErrorCode.ATTESTATION_IDS_NOT_PROVISIONED; // -75;
+ public static final int KM_ERROR_INVALID_OPERATION =
+ ErrorCode.INVALID_OPERATION; // -76;
public static final int KM_ERROR_STORAGE_KEY_UNSUPPORTED =
ErrorCode.STORAGE_KEY_UNSUPPORTED; // -77,
public static final int KM_ERROR_INCOMPATIBLE_MGF_DIGEST =
@@ -348,7 +362,13 @@
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;
+ ErrorCode.MISSING_NOT_AFTER; // -81;
+ public static final int KM_ERROR_MISSING_ISSUER_SUBJECT =
+ ErrorCode.MISSING_ISSUER_SUBJECT; // -82;
+ public static final int KM_ERROR_INVALID_ISSUER_SUBJECT =
+ ErrorCode.INVALID_ISSUER_SUBJECT; // -83;
+ public static final int KM_ERROR_BOOT_LEVEL_EXCEEDED =
+ ErrorCode.BOOT_LEVEL_EXCEEDED; // -84;
public static final int KM_ERROR_HARDWARE_NOT_YET_AVAILABLE =
ErrorCode.HARDWARE_NOT_YET_AVAILABLE; // -85
public static final int KM_ERROR_UNIMPLEMENTED =
diff --git a/core/java/android/security/net/config/ManifestConfigSource.java b/core/java/android/security/net/config/ManifestConfigSource.java
index b885e72..0e20997 100644
--- a/core/java/android/security/net/config/ManifestConfigSource.java
+++ b/core/java/android/security/net/config/ManifestConfigSource.java
@@ -25,7 +25,7 @@
/** @hide */
public class ManifestConfigSource implements ConfigSource {
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final String LOG_TAG = "NetworkSecurityConfig";
private final Object mLock = new Object();
diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS
index 462d8be..162e029 100644
--- a/core/java/android/speech/OWNERS
+++ b/core/java/android/speech/OWNERS
@@ -2,3 +2,4 @@
eugeniom@google.com
schfan@google.com
andreaambu@google.com
+hackz@google.com
\ No newline at end of file
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index d48d566..e6dad27 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -24,12 +24,12 @@
import android.content.Context;
import android.icu.text.DateFormatSymbols;
import android.icu.text.DateTimePatternGenerator;
+import android.icu.util.ULocale;
import android.os.Build;
import android.provider.Settings;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
-import android.text.TextUtils;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -265,11 +265,13 @@
* @return a string pattern suitable for use with {@link java.text.SimpleDateFormat}.
*/
public static String getBestDateTimePattern(Locale locale, String skeleton) {
- DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(locale);
+ ULocale uLocale = ULocale.forLocale(locale);
+ DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(uLocale);
boolean allowDuplicateFields = !CompatChanges.isChangeEnabled(
DISALLOW_DUPLICATE_FIELD_IN_SKELETON);
- return dtpg.getBestPattern(skeleton, DateTimePatternGenerator.MATCH_NO_OPTIONS,
+ String pattern = dtpg.getBestPattern(skeleton, DateTimePatternGenerator.MATCH_NO_OPTIONS,
allowDuplicateFields);
+ return getCompatibleEnglishPattern(uLocale, pattern);
}
/**
@@ -303,10 +305,11 @@
*/
@UnsupportedAppUsage
public static String getTimeFormatString(Context context, int userHandle) {
- DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(
- context.getResources().getConfiguration().locale);
- return is24HourFormat(context, userHandle) ? dtpg.getBestPattern("Hm")
+ ULocale uLocale = ULocale.forLocale(context.getResources().getConfiguration().locale);
+ DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(uLocale);
+ String pattern = is24HourFormat(context, userHandle) ? dtpg.getBestPattern("Hm")
: dtpg.getBestPattern("hm");
+ return getCompatibleEnglishPattern(uLocale, pattern);
}
/**
@@ -713,4 +716,21 @@
public static DateFormatSymbols getIcuDateFormatSymbols(Locale locale) {
return new DateFormatSymbols(android.icu.util.GregorianCalendar.class, locale);
}
+
+ /**
+ * See http://b/266731719. It mirrors the implementation in
+ * {@link libcore.icu.SimpleDateFormatData.DateTimeFormatStringGenerator#postProcessPattern}
+ */
+ private static String getCompatibleEnglishPattern(ULocale locale, String pattern) {
+ if (pattern == null || locale == null || !"en".equals(locale.getLanguage())) {
+ return pattern;
+ }
+
+ String region = locale.getCountry();
+ if (region != null && !region.isEmpty() && !"US".equals(region)) {
+ return pattern;
+ }
+
+ return pattern.replace('\u202f', ' ');
+ }
}
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 3a74b2e..c7f7456 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -138,8 +138,12 @@
mMessageQueue = null;
}
- static final class VsyncEventData {
-
+ /**
+ * Class to capture all inputs required for syncing events data.
+ *
+ * @hide
+ */
+ public static final class VsyncEventData {
static final FrameTimeline[] INVALID_FRAME_TIMELINES =
{new FrameTimeline(FrameInfo.INVALID_VSYNC_ID, Long.MAX_VALUE, Long.MAX_VALUE)};
diff --git a/core/java/android/view/contentcapture/OWNERS b/core/java/android/view/contentcapture/OWNERS
index 1a5cb1e4..43be4f6 100644
--- a/core/java/android/view/contentcapture/OWNERS
+++ b/core/java/android/view/contentcapture/OWNERS
@@ -1,7 +1,4 @@
# Bug component: 544200
-augale@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
-tymtsai@google.com
+hackz@google.com
+volnov@google.com
\ No newline at end of file
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 3df09c2..1f0e95e 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -49,15 +49,18 @@
import java.util.Locale;
/**
- * This widget display an analogic clock with two hands for hours and
- * minutes.
+ * This widget displays an analogic clock with two hands for hours and minutes.
*
* @attr ref android.R.styleable#AnalogClock_dial
* @attr ref android.R.styleable#AnalogClock_hand_hour
* @attr ref android.R.styleable#AnalogClock_hand_minute
* @attr ref android.R.styleable#AnalogClock_hand_second
* @attr ref android.R.styleable#AnalogClock_timeZone
- * @deprecated This widget is no longer supported.
+ * @deprecated This widget is no longer supported; except for
+ * {@link android.widget.RemoteViews} use cases like
+ * <a href="https://developer.android.com/develop/ui/views/appwidgets/overview">
+ * app widgets</a>.
+ *
*/
@RemoteView
@Deprecated
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index fadad99..14aac89 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -709,7 +709,10 @@
}
getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true);
- makeBlink();
+ // Call resumeBlink here instead of makeBlink to ensure that if mBlink is not null the
+ // Blink object is uncancelled. This ensures when a view is removed and added back the
+ // cursor will resume blinking.
+ resumeBlink();
}
void onDetachedFromWindow() {
@@ -1081,8 +1084,10 @@
private void resumeBlink() {
if (mBlink != null) {
mBlink.uncancel();
- makeBlink();
}
+ // Moving makeBlink outside of the null check block ensures that mBlink object gets
+ // instantiated when the view is added to the window if mBlink is still null.
+ makeBlink();
}
void adjustInputType(boolean password, boolean passwordInputType,
@@ -2862,6 +2867,9 @@
if (shouldBlink()) {
mShowCursor = SystemClock.uptimeMillis();
if (mBlink == null) mBlink = new Blink();
+ // Call uncancel as mBlink could have previously been cancelled and cursor will not
+ // resume blinking unless uncancelled.
+ mBlink.uncancel();
mTextView.removeCallbacks(mBlink);
mTextView.postDelayed(mBlink, BLINK);
} else {
diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java
index 2a80d02..740fbac 100644
--- a/core/java/android/window/WindowOrganizer.java
+++ b/core/java/android/window/WindowOrganizer.java
@@ -61,9 +61,7 @@
* Apply multiple WindowContainer operations at once.
*
* Note that using this API requires the caller to hold
- * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}, unless the caller is using
- * {@link TaskFragmentOrganizer}, in which case it is allowed to change TaskFragment that is
- * created by itself.
+ * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS}.
*
* @param t The transaction to apply.
* @param callback This transaction will use the synchronization scheme described in
@@ -72,8 +70,7 @@
* @return An ID for the sync operation which will later be passed to transactionReady callback.
* This lets the caller differentiate overlapping sync operations.
*/
- @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS,
- conditional = true)
+ @RequiresPermission(value = android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
public int applySyncTransaction(@NonNull WindowContainerTransaction t,
@NonNull WindowContainerTransactionCallback callback) {
try {
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index a1d571f..52f18fb 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -1,15 +1,16 @@
per-file *AppOp* = file:/core/java/android/permission/OWNERS
per-file UnlaunchableAppActivity.java = file:/core/java/android/app/admin/WorkProfile_OWNERS
per-file IntentForwarderActivity.java = file:/core/java/android/app/admin/WorkProfile_OWNERS
-per-file *Resolver* = file:/packages/SystemUI/OWNERS
-per-file *Chooser* = file:/packages/SystemUI/OWNERS
-per-file SimpleIconFactory.java = file:/packages/SystemUI/OWNERS
-per-file AbstractMultiProfilePagerAdapter.java = file:/packages/SystemUI/OWNERS
-per-file *EmptyStateProvider.java = file:/packages/SystemUI/OWNERS
per-file NetInitiatedActivity.java = file:/location/java/android/location/OWNERS
per-file *BatteryStats* = file:/BATTERY_STATS_OWNERS
per-file *SoundTrigger* = file:/media/java/android/media/soundtrigger/OWNERS
+# Chooser and Resolver.
+per-file *Chooser* = file:chooser/OWNERS
+per-file *Resolver* = file:chooser/OWNERS
+per-file SimpleIconFactory.java = file:chooser/OWNERS
+per-file AbstractMultiProfilePagerAdapter.java = file:chooser/OWNERS
+per-file *EmptyStateProvider.java = file:chooser/OWNERS
# Voice Interaction
per-file *Assist* = file:/core/java/android/service/voice/OWNERS
diff --git a/core/java/com/android/internal/app/chooser/OWNERS b/core/java/com/android/internal/app/chooser/OWNERS
index a6f1632..0844cfa 100644
--- a/core/java/com/android/internal/app/chooser/OWNERS
+++ b/core/java/com/android/internal/app/chooser/OWNERS
@@ -1 +1,3 @@
-file:/packages/SystemUI/OWNERS
\ No newline at end of file
+# Bug component: 324112
+
+include platform/packages/modules/IntentResolver:/OWNERS
diff --git a/core/java/com/android/internal/expresslog/Counter.java b/core/java/com/android/internal/expresslog/Counter.java
deleted file mode 100644
index 4a46d91..0000000
--- a/core/java/com/android/internal/expresslog/Counter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.expresslog;
-
-import android.annotation.NonNull;
-
-import com.android.internal.util.FrameworkStatsLog;
-
-/** Counter encapsulates StatsD write API calls */
-public final class Counter {
-
- // Not instantiable.
- private Counter() {}
-
- /**
- * Increments Telemetry Express Counter metric by 1
- * @param metricId to log, no-op if metricId is not defined in the TeX catalog
- * @hide
- */
- public static void logIncrement(@NonNull String metricId) {
- logIncrement(metricId, 1);
- }
-
- /**
- * Increments Telemetry Express Counter metric by 1
- * @param metricId to log, no-op if metricId is not defined in the TeX catalog
- * @param uid used as a dimension for the count metric
- * @hide
- */
- public static void logIncrementWithUid(@NonNull String metricId, int uid) {
- logIncrementWithUid(metricId, uid, 1);
- }
-
- /**
- * Increments Telemetry Express Counter metric by arbitrary value
- * @param metricId to log, no-op if metricId is not defined in the TeX catalog
- * @param amount to increment counter
- * @hide
- */
- public static void logIncrement(@NonNull String metricId, long amount) {
- final long metricIdHash = Utils.hashString(metricId);
- FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_EVENT_REPORTED, metricIdHash, amount);
- }
-
- /**
- * Increments Telemetry Express Counter metric by arbitrary value
- * @param metricId to log, no-op if metricId is not defined in the TeX catalog
- * @param uid used as a dimension for the count metric
- * @param amount to increment counter
- * @hide
- */
- public static void logIncrementWithUid(@NonNull String metricId, int uid, long amount) {
- final long metricIdHash = Utils.hashString(metricId);
- FrameworkStatsLog.write(
- FrameworkStatsLog.EXPRESS_UID_EVENT_REPORTED, metricIdHash, amount, uid);
- }
-}
diff --git a/core/java/com/android/internal/expresslog/Histogram.java b/core/java/com/android/internal/expresslog/Histogram.java
deleted file mode 100644
index 65fbb03..0000000
--- a/core/java/com/android/internal/expresslog/Histogram.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.expresslog;
-
-import android.annotation.FloatRange;
-import android.annotation.IntRange;
-import android.annotation.NonNull;
-
-import com.android.internal.util.FrameworkStatsLog;
-
-import java.util.Arrays;
-
-/** Histogram encapsulates StatsD write API calls */
-public final class Histogram {
-
- private final long mMetricIdHash;
- private final BinOptions mBinOptions;
-
- /**
- * Creates Histogram metric logging wrapper
- *
- * @param metricId to log, logging will be no-op if metricId is not defined in the TeX catalog
- * @param binOptions to calculate bin index for samples
- * @hide
- */
- public Histogram(@NonNull String metricId, @NonNull BinOptions binOptions) {
- mMetricIdHash = Utils.hashString(metricId);
- mBinOptions = binOptions;
- }
-
- /**
- * Logs increment sample count for automatically calculated bin
- *
- * @param sample value
- * @hide
- */
- public void logSample(float sample) {
- final int binIndex = mBinOptions.getBinForSample(sample);
- FrameworkStatsLog.write(FrameworkStatsLog.EXPRESS_HISTOGRAM_SAMPLE_REPORTED, mMetricIdHash,
- /*count*/ 1, binIndex);
- }
-
- /** Used by Histogram to map data sample to corresponding bin */
- public interface BinOptions {
- /**
- * Returns bins count to be used by a histogram
- *
- * @return bins count used to initialize Options, including overflow & underflow bins
- * @hide
- */
- int getBinsCount();
-
- /**
- * Returns bin index for the input sample value
- * index == 0 stands for underflow
- * index == getBinsCount() - 1 stands for overflow
- *
- * @return zero based index
- * @hide
- */
- int getBinForSample(float sample);
- }
-
- /** Used by Histogram to map data sample to corresponding bin for uniform bins */
- public static final class UniformOptions implements BinOptions {
-
- private final int mBinCount;
- private final float mMinValue;
- private final float mExclusiveMaxValue;
- private final float mBinSize;
-
- /**
- * Creates options for uniform (linear) sized bins
- *
- * @param binCount amount of histogram bins. 2 bin indexes will be calculated
- * automatically to represent underflow & overflow bins
- * @param minValue is included in the first bin, values less than minValue
- * go to underflow bin
- * @param exclusiveMaxValue is included in the overflow bucket. For accurate
- * measure up to kMax, then exclusiveMaxValue
- * should be set to kMax + 1
- * @hide
- */
- public UniformOptions(@IntRange(from = 1) int binCount, float minValue,
- float exclusiveMaxValue) {
- if (binCount < 1) {
- throw new IllegalArgumentException("Bin count should be positive number");
- }
-
- if (exclusiveMaxValue <= minValue) {
- throw new IllegalArgumentException("Bins range invalid (maxValue < minValue)");
- }
-
- mMinValue = minValue;
- mExclusiveMaxValue = exclusiveMaxValue;
- mBinSize = (mExclusiveMaxValue - minValue) / binCount;
-
- // Implicitly add 2 for the extra underflow & overflow bins
- mBinCount = binCount + 2;
- }
-
- @Override
- public int getBinsCount() {
- return mBinCount;
- }
-
- @Override
- public int getBinForSample(float sample) {
- if (sample < mMinValue) {
- // goes to underflow
- return 0;
- } else if (sample >= mExclusiveMaxValue) {
- // goes to overflow
- return mBinCount - 1;
- }
- return (int) ((sample - mMinValue) / mBinSize + 1);
- }
- }
-
- /** Used by Histogram to map data sample to corresponding bin for scaled bins */
- public static final class ScaledRangeOptions implements BinOptions {
- // store minimum value per bin
- final long[] mBins;
-
- /**
- * Creates options for scaled range bins
- *
- * @param binCount amount of histogram bins. 2 bin indexes will be calculated
- * automatically to represent underflow & overflow bins
- * @param minValue is included in the first bin, values less than minValue
- * go to underflow bin
- * @param firstBinWidth used to represent first bin width and as a reference to calculate
- * width for consecutive bins
- * @param scaleFactor used to calculate width for consecutive bins
- * @hide
- */
- public ScaledRangeOptions(@IntRange(from = 1) int binCount, int minValue,
- @FloatRange(from = 1.f) float firstBinWidth,
- @FloatRange(from = 1.f) float scaleFactor) {
- if (binCount < 1) {
- throw new IllegalArgumentException("Bin count should be positive number");
- }
-
- if (firstBinWidth < 1.f) {
- throw new IllegalArgumentException(
- "First bin width invalid (should be 1.f at minimum)");
- }
-
- if (scaleFactor < 1.f) {
- throw new IllegalArgumentException(
- "Scaled factor invalid (should be 1.f at minimum)");
- }
-
- // precalculating bins ranges (no need to create a bin for underflow reference value)
- mBins = initBins(binCount + 1, minValue, firstBinWidth, scaleFactor);
- }
-
- @Override
- public int getBinsCount() {
- return mBins.length + 1;
- }
-
- @Override
- public int getBinForSample(float sample) {
- if (sample < mBins[0]) {
- // goes to underflow
- return 0;
- } else if (sample >= mBins[mBins.length - 1]) {
- // goes to overflow
- return mBins.length;
- }
-
- return lower_bound(mBins, (long) sample) + 1;
- }
-
- // To find lower bound using binary search implementation of Arrays utility class
- private static int lower_bound(long[] array, long sample) {
- int index = Arrays.binarySearch(array, sample);
- // If key is not present in the array
- if (index < 0) {
- // Index specify the position of the key when inserted in the sorted array
- // so the element currently present at this position will be the lower bound
- return Math.abs(index) - 2;
- }
- return index;
- }
-
- private static long[] initBins(int count, int minValue, float firstBinWidth,
- float scaleFactor) {
- long[] bins = new long[count];
- bins[0] = minValue;
- double lastWidth = firstBinWidth;
- for (int i = 1; i < count; i++) {
- // current bin minValue = previous bin width * scaleFactor
- double currentBinMinValue = bins[i - 1] + lastWidth;
- if (currentBinMinValue > Integer.MAX_VALUE) {
- throw new IllegalArgumentException(
- "Attempted to create a bucket larger than maxint");
- }
-
- bins[i] = (long) currentBinMinValue;
- lastWidth *= scaleFactor;
- }
- return bins;
- }
- }
-}
diff --git a/core/java/com/android/internal/expresslog/OWNERS b/core/java/com/android/internal/expresslog/OWNERS
deleted file mode 100644
index ee865b1..0000000
--- a/core/java/com/android/internal/expresslog/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include /services/core/java/com/android/server/stats/OWNERS
diff --git a/core/java/com/android/internal/expresslog/TEST_MAPPING b/core/java/com/android/internal/expresslog/TEST_MAPPING
deleted file mode 100644
index c9b0cf8..0000000
--- a/core/java/com/android/internal/expresslog/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "ExpressLogTests",
- "options": [
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- }
- ]
-}
\ No newline at end of file
diff --git a/core/java/com/android/internal/expresslog/Utils.java b/core/java/com/android/internal/expresslog/Utils.java
deleted file mode 100644
index d82192f..0000000
--- a/core/java/com/android/internal/expresslog/Utils.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.expresslog;
-
-final class Utils {
- static native long hashString(String stringToHash);
-}
diff --git a/core/java/com/android/internal/jank/OWNERS b/core/java/com/android/internal/jank/OWNERS
index 352c132..2f3bbee 100644
--- a/core/java/com/android/internal/jank/OWNERS
+++ b/core/java/com/android/internal/jank/OWNERS
@@ -3,4 +3,5 @@
# Jank people
ahanwu@google.com
vadimt@google.com
-marcinoc@google.com
\ No newline at end of file
+marcinoc@google.com
+pmuetschard@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 05cad77..d8aeb51 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -1018,7 +1018,7 @@
* Applies debugger system properties to the zygote arguments.
*
* For eng builds all apps are debuggable. On userdebug and user builds
- * if persist.debuggable.dalvik.vm.jdwp.enabled is 1 all apps are
+ * if persist.debug.dalvik.vm.jdwp.enabled is 1 all apps are
* debuggable. Otherwise, the debugger state is specified via the
* "--enable-jdwp" flag in the spawn request.
*
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index b5b7c0f..73c93ac 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -221,7 +221,6 @@
"android_content_res_Configuration.cpp",
"android_security_Scrypt.cpp",
"com_android_internal_content_om_OverlayConfig.cpp",
- "com_android_internal_expresslog_Utils.cpp",
"com_android_internal_net_NetworkUtilsInternal.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
@@ -256,6 +255,7 @@
"libstatssocket_lazy",
"libskia",
"libtextclassifier_hash_static",
+ "libexpresslog_jni",
],
shared_libs: [
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9c7f0a8..7c8ea93 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -195,8 +195,7 @@
extern int register_android_security_Scrypt(JNIEnv *env);
extern int register_com_android_internal_content_F2fsUtils(JNIEnv* env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
-extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
-extern int register_com_android_internal_expresslog_Utils(JNIEnv* env);
+extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv* env);
extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
@@ -213,6 +212,7 @@
extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env);
extern int register_com_android_internal_security_VerityUtils(JNIEnv* env);
extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
+extern int register_com_android_modules_expresslog_Utils(JNIEnv* env);
extern int register_android_window_WindowInfosListener(JNIEnv* env);
// Namespace for Android Runtime flags applied during boot time.
@@ -646,9 +646,7 @@
char saveResolvedClassesDelayMsOptsBuf[
sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX];
char profileMinSavePeriodOptsBuf[sizeof("-Xps-min-save-period-ms:")-1 + PROPERTY_VALUE_MAX];
- char profileMinFirstSaveOptsBuf[
- sizeof("-Xps-min-first-save-ms:")-1 + PROPERTY_VALUE_MAX];
- char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX];
+ char profileMinFirstSaveOptsBuf[sizeof("-Xps-min-first-save-ms:") - 1 + PROPERTY_VALUE_MAX];
char madviseWillNeedFileSizeVdex[
sizeof("-XMadviseWillNeedVdexFileSize:")-1 + PROPERTY_VALUE_MAX];
char madviseWillNeedFileSizeOdex[
@@ -861,13 +859,8 @@
jitprithreadweightOptBuf,
"-Xjitprithreadweight:");
- parseRuntimeOption("dalvik.vm.jittransitionweight",
- jittransitionweightOptBuf,
+ parseRuntimeOption("dalvik.vm.jittransitionweight", jittransitionweightOptBuf,
"-Xjittransitionweight:");
- /*
- * Madvise related options.
- */
- parseRuntimeOption("dalvik.vm.madvise-random", madviseRandomOptsBuf, "-XX:MadviseRandomAccess:");
/*
* Use default platform configuration as limits for madvising,
@@ -1591,7 +1584,6 @@
REG_JNI(register_android_os_SharedMemory),
REG_JNI(register_android_os_incremental_IncrementalManager),
REG_JNI(register_com_android_internal_content_om_OverlayConfig),
- REG_JNI(register_com_android_internal_expresslog_Utils),
REG_JNI(register_com_android_internal_net_NetworkUtilsInternal),
REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
REG_JNI(register_com_android_internal_os_LongArrayMultiStateCounter),
@@ -1601,6 +1593,7 @@
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_com_android_internal_security_VerityUtils),
REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
+ REG_JNI(register_com_android_modules_expresslog_Utils),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_camera2_CameraMetadata),
REG_JNI(register_android_hardware_camera2_DngCreator),
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 1e7a93c..84b050c 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -102,6 +102,3 @@
# PM
per-file com_android_internal_content_* = file:/PACKAGE_MANAGER_OWNERS
-
-# Stats/expresslog
-per-file *expresslog* = file:/services/core/java/com/android/server/stats/OWNERS
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index cdb0580..56c2a86 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2382,36 +2382,31 @@
if (jSurroundFormats == nullptr) {
ALOGE("jSurroundFormats is NULL");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return static_cast<jint>(AUDIO_JAVA_BAD_VALUE);
}
if (!env->IsInstanceOf(jSurroundFormats, gMapClass)) {
ALOGE("getSurroundFormats not a map");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return static_cast<jint>(AUDIO_JAVA_BAD_VALUE);
}
jint jStatus;
unsigned int numSurroundFormats = 0;
- audio_format_t *surroundFormats = nullptr;
- bool *surroundFormatsEnabled = nullptr;
- status_t status = AudioSystem::getSurroundFormats(&numSurroundFormats, surroundFormats,
- surroundFormatsEnabled);
+ status_t status = AudioSystem::getSurroundFormats(&numSurroundFormats, nullptr, nullptr);
if (status != NO_ERROR) {
ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
- jStatus = nativeToJavaStatus(status);
- goto exit;
+ return nativeToJavaStatus(status);
}
if (numSurroundFormats == 0) {
- jStatus = (jint)AUDIO_JAVA_SUCCESS;
- goto exit;
+ return static_cast<jint>(AUDIO_JAVA_SUCCESS);
}
- surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t));
- surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool));
- status = AudioSystem::getSurroundFormats(&numSurroundFormats, surroundFormats,
- surroundFormatsEnabled);
+ auto surroundFormats = std::make_unique<audio_format_t[]>(numSurroundFormats);
+ auto surroundFormatsEnabled = std::make_unique<bool[]>(numSurroundFormats);
+ status = AudioSystem::getSurroundFormats(&numSurroundFormats, &surroundFormats[0],
+ &surroundFormatsEnabled[0]);
jStatus = nativeToJavaStatus(status);
if (status != NO_ERROR) {
ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
- goto exit;
+ return jStatus;
}
for (size_t i = 0; i < numSurroundFormats; i++) {
int audioFormat = audioFormatFromNative(surroundFormats[i]);
@@ -2427,9 +2422,6 @@
env->DeleteLocalRef(enabled);
}
-exit:
- free(surroundFormats);
- free(surroundFormatsEnabled);
return jStatus;
}
@@ -2439,31 +2431,28 @@
if (jSurroundFormats == nullptr) {
ALOGE("jSurroundFormats is NULL");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return static_cast<jint>(AUDIO_JAVA_BAD_VALUE);
}
if (!env->IsInstanceOf(jSurroundFormats, gArrayListClass)) {
ALOGE("jSurroundFormats not an arraylist");
- return (jint)AUDIO_JAVA_BAD_VALUE;
+ return static_cast<jint>(AUDIO_JAVA_BAD_VALUE);
}
jint jStatus;
unsigned int numSurroundFormats = 0;
- audio_format_t *surroundFormats = nullptr;
- status_t status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, surroundFormats);
+ status_t status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, nullptr);
if (status != NO_ERROR) {
ALOGE_IF(status != NO_ERROR, "AudioSystem::getReportedSurroundFormats error %d", status);
- jStatus = nativeToJavaStatus(status);
- goto exit;
+ return nativeToJavaStatus(status);
}
if (numSurroundFormats == 0) {
- jStatus = (jint)AUDIO_JAVA_SUCCESS;
- goto exit;
+ return static_cast<jint>(AUDIO_JAVA_SUCCESS);
}
- surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t));
- status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, surroundFormats);
+ auto surroundFormats = std::make_unique<audio_format_t[]>(numSurroundFormats);
+ status = AudioSystem::getReportedSurroundFormats(&numSurroundFormats, &surroundFormats[0]);
jStatus = nativeToJavaStatus(status);
if (status != NO_ERROR) {
ALOGE_IF(status != NO_ERROR, "AudioSystem::getReportedSurroundFormats error %d", status);
- goto exit;
+ return jStatus;
}
for (size_t i = 0; i < numSurroundFormats; i++) {
int audioFormat = audioFormatFromNative(surroundFormats[i]);
@@ -2477,8 +2466,6 @@
env->DeleteLocalRef(surroundFormat);
}
-exit:
- free(surroundFormats);
return jStatus;
}
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index a7c7d0b..8bc52b8 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -413,9 +413,13 @@
if (env->ExceptionCheck()) {
ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
- binder_report_exception(env, excep.get(),
- "*** Uncaught remote exception! "
- "(Exceptions are not yet supported across processes.)");
+
+ auto state = IPCThreadState::self();
+ String8 msg;
+ msg.appendFormat("*** Uncaught remote exception! Exceptions are not yet supported "
+ "across processes. Client PID %d UID %d.",
+ state->getCallingPid(), state->getCallingUid());
+ binder_report_exception(env, excep.get(), msg.c_str());
res = JNI_FALSE;
}
@@ -431,6 +435,7 @@
ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred());
binder_report_exception(env, excep.get(),
"*** Uncaught exception in onBinderStrictModePolicyChange");
+ // TODO: should turn this to fatal?
}
// Need to always call through the native implementation of
@@ -969,7 +974,7 @@
return IPCThreadState::self()->getCallingUid();
}
-static jboolean android_os_Binder_isDirectlyHandlingTransaction() {
+static jboolean android_os_Binder_isDirectlyHandlingTransactionNative() {
return getCurrentServingCall() == BinderCallType::BINDER;
}
@@ -1077,7 +1082,8 @@
// @CriticalNative
{ "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid },
// @CriticalNative
- { "isDirectlyHandlingTransaction", "()Z", (void*)android_os_Binder_isDirectlyHandlingTransaction },
+ { "isDirectlyHandlingTransactionNative", "()Z",
+ (void*)android_os_Binder_isDirectlyHandlingTransactionNative },
// @CriticalNative
{ "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity },
// @CriticalNative
diff --git a/core/jni/com_android_internal_expresslog_Utils.cpp b/core/jni/com_android_internal_expresslog_Utils.cpp
deleted file mode 100644
index d33a7bd..0000000
--- a/core/jni/com_android_internal_expresslog_Utils.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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 <nativehelper/JNIHelp.h>
-#include <utils/hash/farmhash.h>
-
-#include "core_jni_helpers.h"
-
-// ----------------------------------------------------------------------------
-// JNI Glue
-// ----------------------------------------------------------------------------
-
-static jclass g_stringClass = nullptr;
-
-/**
- * Class: com_android_internal_expresslog_Utils
- * Method: hashString
- * Signature: (Ljava/lang/String;)J
- */
-static jlong hashString(JNIEnv* env, jclass /*class*/, jstring metricNameObj) {
- ScopedUtfChars name(env, metricNameObj);
- if (name.c_str() == nullptr) {
- return 0;
- }
-
- return static_cast<jlong>(farmhash::Fingerprint64(name.c_str(), name.size()));
-}
-
-static const JNINativeMethod g_methods[] = {
- {"hashString", "(Ljava/lang/String;)J", (void*)hashString},
-};
-
-static const char* const kUtilsPathName = "com/android/internal/expresslog/Utils";
-
-namespace android {
-
-int register_com_android_internal_expresslog_Utils(JNIEnv* env) {
- jclass stringClass = FindClassOrDie(env, "java/lang/String");
- g_stringClass = MakeGlobalRefOrDie(env, stringClass);
-
- return RegisterMethodsOrDie(env, kUtilsPathName, g_methods, NELEM(g_methods));
-}
-
-} // namespace android
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index a5152b6..56c01ba2 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -23,43 +23,13 @@
namespace {
-// Shadow call stack (SCS) is a security mitigation that uses a separate stack
-// (the SCS) for return addresses. In versions of Android newer than P, the
-// compiler cooperates with the system to ensure that the SCS address is always
-// stored in register x18, as long as the app was compiled with a new enough
-// compiler and does not use features that rely on SP-HALs (this restriction is
-// because the SP-HALs might not preserve x18 due to potentially having been
-// compiled with an old compiler as a consequence of Treble; it generally means
-// that the app must be a system app without a UI). This struct is used to
-// temporarily store the address on the stack while preloading the SP-HALs, so
-// that such apps can use the same zygote as everything else.
-struct ScopedSCSExit {
-#ifdef __aarch64__
- void* scs;
-
- ScopedSCSExit() {
- __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
- }
-
- ~ScopedSCSExit() {
- __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
- }
-#else
- // Silence unused variable warnings in non-SCS builds.
- ScopedSCSExit() {}
- ~ScopedSCSExit() {}
-#endif
-};
-
void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) {
- ScopedSCSExit x;
android::GraphicBufferMapper::preloadHal();
// Add preloading here for other HALs that are (a) always passthrough, and
// (b) loaded by most app processes.
}
void android_internal_os_ZygoteInit_nativePreloadGraphicsDriver(JNIEnv* env, jclass) {
- ScopedSCSExit x;
zygote_preload_graphics();
}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 7205dd8..c596c54 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -1008,6 +1008,7 @@
optional int32 uid = 1;
repeated .android.app.ApplicationExitInfoProto app_exit_info = 2;
+ repeated .android.app.ApplicationExitInfoProto app_recoverable_crash = 3;
}
repeated User users = 2;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a5e9617..35dc8e3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1334,8 +1334,7 @@
android:permissionFlags="hardRestricted"
android:protectionLevel="dangerous" />
- <!-- Allows an application to write (but not read) the user's
- call log data.
+ <!-- Allows an application to write and read the user's call log data.
<p class="note"><strong>Note:</strong> If your app uses the
{@link #WRITE_CONTACTS} permission and <em>both</em> your <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
@@ -2329,6 +2328,8 @@
<p>Protection level: normal
-->
<permission android:name="android.permission.NFC_TRANSACTION_EVENT"
+ android:description="@string/permdesc_nfcTransactionEvent"
+ android:label="@string/permlab_nfcTransactionEvent"
android:protectionLevel="normal" />
<!-- Allows applications to receive NFC preferred payment service information.
@@ -4238,11 +4239,11 @@
android:protectionLevel="internal|preinstalled" />
<!-- Allows an application to subscribe to keyguard locked (i.e., showing) state.
- <p>Protection level: internal|role
- <p>Intended for use by ROLE_ASSISTANT only.
+ <p>Protection level: signature|role
+ <p>Intended for use by ROLE_ASSISTANT and signature apps only.
-->
<permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE"
- android:protectionLevel="internal|role"/>
+ android:protectionLevel="signature|role"/>
<!-- Must be required by a {@link android.service.autofill.AutofillService},
to ensure that only the system can bind to it.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4b05f99..031a666 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4475,6 +4475,9 @@
<!-- Whether or not we should show the option to show battery percentage -->
<bool name="config_battery_percentage_setting_available">true</bool>
+ <!-- Default value set for battery percentage in status bar false = disabled, true = enabled -->
+ <bool name="config_defaultBatteryPercentageSetting">false</bool>
+
<!-- Whether or not battery saver should be "sticky" when manually enabled. -->
<bool name="config_batterySaverStickyBehaviourDisabled">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8a1b74d..5a1e0e8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1604,6 +1604,12 @@
with Near Field Communication (NFC) tags, cards, and readers.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_nfcTransactionEvent">Secure Element transaction event</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_nfcTransactionEvent">Allows the app to receive information about
+ transactions happening on a Secure Element.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_disableKeyguard">disable your screen lock</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_disableKeyguard">Allows the app to disable the
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ba1030b..716d1bd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2359,6 +2359,7 @@
<java-symbol type="style" name="Animation.RecentApplications" />
<java-symbol type="integer" name="dock_enter_exit_duration" />
<java-symbol type="bool" name="config_battery_percentage_setting_available" />
+ <java-symbol type="bool" name="config_defaultBatteryPercentageSetting" />
<java-symbol type="string" name="nas_upgrade_notification_title" />
<java-symbol type="string" name="nas_upgrade_notification_content" />
<java-symbol type="string" name="nas_upgrade_notification_enable_action" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 48c9df0..035eaee 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -84,8 +84,8 @@
":BstatsTestApp",
":BinderDeathRecipientHelperApp1",
":BinderDeathRecipientHelperApp2",
+ ":com.android.cts.helpers.aosp",
],
- required: ["com.android.cts.helpers.aosp"],
}
// Rules to copy all the test apks to the intermediate raw resource directory
diff --git a/core/tests/coretests/src/android/app/OWNERS b/core/tests/coretests/src/android/app/OWNERS
index b3f3993..8d9461d 100644
--- a/core/tests/coretests/src/android/app/OWNERS
+++ b/core/tests/coretests/src/android/app/OWNERS
@@ -4,3 +4,6 @@
per-file *Notification* = file:/packages/SystemUI/OWNERS
per-file *Zen* = file:/packages/SystemUI/OWNERS
per-file *StatusBar* = file:/packages/SystemUI/OWNERS
+
+# A11Y and related
+per-file *UiAutomation* = file:/services/accessibility/OWNERS
diff --git a/core/tests/coretests/src/android/os/ParcelTest.java b/core/tests/coretests/src/android/os/ParcelTest.java
index e2fe87b4..4b993fa 100644
--- a/core/tests/coretests/src/android/os/ParcelTest.java
+++ b/core/tests/coretests/src/android/os/ParcelTest.java
@@ -246,4 +246,93 @@
assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, -1, pB, iB, 0));
assertThrows(IllegalArgumentException.class, () -> Parcel.compareData(pA, 0, pB, -1, 0));
}
+
+ /***
+ * Tests for b/205282403
+ * This test checks if allocations made over limit of 1MB for primitive types
+ * and 1M length for complex objects are not allowed.
+ */
+ @Test
+ public void testAllocationsOverLimit_whenOverLimit_throws() {
+ Binder.setIsDirectlyHandlingTransactionOverride(true);
+ Parcel p = Parcel.obtain();
+ p.setDataPosition(0);
+ p.writeInt(Integer.MAX_VALUE);
+
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class, () ->p.createBooleanArray());
+
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class, () ->p.createCharArray());
+
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class, () ->p.createIntArray());
+
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class, () ->p.createLongArray());
+
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class, () ->p.createBinderArray());
+
+ int[] dimensions = new int[]{Integer.MAX_VALUE, 100, 100};
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class,
+ () -> p.createFixedArray(int[][][].class, dimensions));
+
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class,
+ () -> p.createFixedArray(String[][][].class, dimensions));
+
+ p.setDataPosition(0);
+ assertThrows(BadParcelableException.class,
+ () -> p.createFixedArray(IBinder[][][].class, dimensions));
+
+ p.recycle();
+ Binder.setIsDirectlyHandlingTransactionOverride(false);
+ }
+
+ /***
+ * Tests for b/205282403
+ * This test checks if allocations made under limit of 1MB for primitive types
+ * and 1M length for complex objects are allowed.
+ */
+ @Test
+ public void testAllocations_whenWithinLimit() {
+ Binder.setIsDirectlyHandlingTransactionOverride(true);
+ Parcel p = Parcel.obtain();
+ p.setDataPosition(0);
+ p.writeInt(100000);
+
+ p.setDataPosition(0);
+ p.createByteArray();
+
+ p.setDataPosition(0);
+ p.createCharArray();
+
+ p.setDataPosition(0);
+ p.createIntArray();
+
+ p.setDataPosition(0);
+ p.createLongArray();
+
+ p.setDataPosition(0);
+ p.createBinderArray();
+
+ int[] dimensions = new int[]{ 100, 100, 100 };
+
+ p.setDataPosition(0);
+ int[][][] data = new int[100][100][100];
+ p.writeFixedArray(data, 0, dimensions);
+ p.setDataPosition(0);
+ p.createFixedArray(int[][][].class, dimensions);
+
+ p.setDataPosition(0);
+ IBinder[][][] parcelables = new IBinder[100][100][100];
+ p.writeFixedArray(parcelables, 0, dimensions);
+ p.setDataPosition(0);
+ p.createFixedArray(IBinder[][][].class, dimensions);
+
+ p.recycle();
+ Binder.setIsDirectlyHandlingTransactionOverride(false);
+ }
}
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
index 52846df..b2ffdc0 100644
--- a/core/tests/coretests/src/android/os/ProcessTest.java
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -73,6 +73,7 @@
}
public void testGetAdvertisedMem() {
+ assertTrue(Process.getAdvertisedMem() > 0);
assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem());
}
}
diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java
index 8459330..212cc44 100644
--- a/core/tests/coretests/src/android/text/format/DateFormatTest.java
+++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java
@@ -156,8 +156,8 @@
@DisableCompatChanges({DateFormat.DISALLOW_DUPLICATE_FIELD_IN_SKELETON})
public void testGetBestDateTimePattern_enableDuplicateField() {
// en-US uses 12-hour format by default.
- assertEquals("h:mm\u202fa", DateFormat.getBestDateTimePattern(Locale.US, "jmma"));
- assertEquals("h:mm\u202fa", DateFormat.getBestDateTimePattern(Locale.US, "ahmma"));
+ assertEquals("h:mm a", DateFormat.getBestDateTimePattern(Locale.US, "jmma"));
+ assertEquals("h:mm a", DateFormat.getBestDateTimePattern(Locale.US, "ahmma"));
}
private static void assertIllegalArgumentException(Locale l, String skeleton) {
diff --git a/core/tests/coretests/src/android/text/format/DateUtilsTest.java b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
index 39ed82ef..381c051 100644
--- a/core/tests/coretests/src/android/text/format/DateUtilsTest.java
+++ b/core/tests/coretests/src/android/text/format/DateUtilsTest.java
@@ -139,16 +139,16 @@
fixedTime, java.text.DateFormat.SHORT, java.text.DateFormat.FULL));
final long hourDuration = 2 * 60 * 60 * 1000;
- assertEquals("5:30:15\u202fAM Greenwich Mean Time", DateUtils.formatSameDayTime(
+ assertEquals("5:30:15 AM Greenwich Mean Time", DateUtils.formatSameDayTime(
fixedTime + hourDuration, fixedTime, java.text.DateFormat.FULL,
java.text.DateFormat.FULL));
- assertEquals("5:30:15\u202fAM", DateUtils.formatSameDayTime(fixedTime + hourDuration,
+ assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration,
fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.DEFAULT));
- assertEquals("5:30:15\u202fAM GMT", DateUtils.formatSameDayTime(fixedTime + hourDuration,
+ assertEquals("5:30:15 AM GMT", DateUtils.formatSameDayTime(fixedTime + hourDuration,
fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.LONG));
- assertEquals("5:30:15\u202fAM", DateUtils.formatSameDayTime(fixedTime + hourDuration,
+ assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration,
fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.MEDIUM));
- assertEquals("5:30\u202fAM", DateUtils.formatSameDayTime(fixedTime + hourDuration,
+ assertEquals("5:30 AM", DateUtils.formatSameDayTime(fixedTime + hourDuration,
fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.SHORT));
}
diff --git a/core/tests/expresslog/Android.bp b/core/tests/expresslog/Android.bp
deleted file mode 100644
index cab49a7..0000000
--- a/core/tests/expresslog/Android.bp
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2023 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-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"],
-}
-
-android_test {
- name: "ExpressLogTests",
-
- srcs: [
- "src/**/*.java",
- ],
-
- static_libs: [
- "androidx.test.rules",
- "modules-utils-build",
- ],
-
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
-
- platform_apis: true,
- test_suites: [
- "general-tests",
- ],
-
- certificate: "platform",
-}
diff --git a/core/tests/expresslog/AndroidManifest.xml b/core/tests/expresslog/AndroidManifest.xml
deleted file mode 100644
index 94a39e0..0000000
--- a/core/tests/expresslog/AndroidManifest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- android:installLocation="internalOnly"
- package="com.android.internal.expresslog" >
-
- <application >
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.internal.expresslog"
- android:label="Telemetry Express Logging Helper Tests" />
-
-</manifest>
diff --git a/core/tests/expresslog/OWNERS b/core/tests/expresslog/OWNERS
deleted file mode 100644
index 3dc958b..0000000
--- a/core/tests/expresslog/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 719316
-# Stats/expresslog
-file:/services/core/java/com/android/server/stats/OWNERS
diff --git a/core/tests/expresslog/TEST_MAPPING b/core/tests/expresslog/TEST_MAPPING
deleted file mode 100644
index c9b0cf8..0000000
--- a/core/tests/expresslog/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "ExpressLogTests",
- "options": [
- {
- "exclude-annotation": "org.junit.Ignore"
- }
- ]
- }
- ]
-}
\ No newline at end of file
diff --git a/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java b/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java
deleted file mode 100644
index ee62d75..0000000
--- a/core/tests/expresslog/src/com/android/internal/expresslog/ScaledRangeOptionsTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.expresslog;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-@SmallTest
-public class ScaledRangeOptionsTest {
- private static final String TAG = ScaledRangeOptionsTest.class.getSimpleName();
-
- @Test
- public void testGetBinsCount() {
- Histogram.ScaledRangeOptions options1 = new Histogram.ScaledRangeOptions(1, 100, 100, 2);
- assertEquals(3, options1.getBinsCount());
-
- Histogram.ScaledRangeOptions options10 = new Histogram.ScaledRangeOptions(10, 100, 100, 2);
- assertEquals(12, options10.getBinsCount());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructZeroBinsCount() {
- new Histogram.ScaledRangeOptions(0, 100, 100, 2);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructNegativeBinsCount() {
- new Histogram.ScaledRangeOptions(-1, 100, 100, 2);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructNegativeFirstBinWidth() {
- new Histogram.ScaledRangeOptions(10, 100, -100, 2);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructTooSmallFirstBinWidth() {
- new Histogram.ScaledRangeOptions(10, 100, 0.5f, 2);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructNegativeScaleFactor() {
- new Histogram.ScaledRangeOptions(10, 100, 100, -2);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructTooSmallScaleFactor() {
- new Histogram.ScaledRangeOptions(10, 100, 100, 0.5f);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructTooBigScaleFactor() {
- new Histogram.ScaledRangeOptions(10, 100, 100, 500.f);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructTooBigBinRange() {
- new Histogram.ScaledRangeOptions(100, 100, 100, 10.f);
- }
-
- @Test
- public void testBinIndexForRangeEqual1() {
- Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 1, 1);
- assertEquals(12, options.getBinsCount());
-
- assertEquals(11, options.getBinForSample(11));
-
- for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
- assertEquals(i, options.getBinForSample(i));
- }
- }
-
- @Test
- public void testBinIndexForRangeEqual2() {
- // this should produce bin otpions similar to linear histogram with bin width 2
- Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 2, 1);
- assertEquals(12, options.getBinsCount());
-
- for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
- assertEquals(i, options.getBinForSample(i * 2));
- assertEquals(i, options.getBinForSample(i * 2 - 1));
- }
- }
-
- @Test
- public void testBinIndexForRangeEqual5() {
- Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(2, 0, 5, 1);
- assertEquals(4, options.getBinsCount());
- for (int i = 0; i < 2; i++) {
- for (int sample = 0; sample < 5; sample++) {
- assertEquals(i + 1, options.getBinForSample(i * 5 + sample));
- }
- }
- }
-
- @Test
- public void testBinIndexForRangeEqual10() {
- Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(10, 1, 10, 1);
- assertEquals(0, options.getBinForSample(0));
- assertEquals(options.getBinsCount() - 2, options.getBinForSample(100));
- assertEquals(options.getBinsCount() - 1, options.getBinForSample(101));
-
- final float binSize = (101 - 1) / 10f;
- for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) {
- assertEquals(i, options.getBinForSample(i * binSize));
- }
- }
-
- @Test
- public void testBinIndexForScaleFactor2() {
- final int binsCount = 10;
- final int minValue = 10;
- final int firstBinWidth = 5;
- final int scaledFactor = 2;
-
- Histogram.ScaledRangeOptions options = new Histogram.ScaledRangeOptions(
- binsCount, minValue, firstBinWidth, scaledFactor);
- assertEquals(binsCount + 2, options.getBinsCount());
- long[] binCounts = new long[10];
-
- // precalculate max valid value - start value for the overflow bin
- int lastBinStartValue = minValue; //firstBinMin value
- int lastBinWidth = firstBinWidth;
- for (int binIdx = 2; binIdx <= binsCount + 1; binIdx++) {
- lastBinStartValue = lastBinStartValue + lastBinWidth;
- lastBinWidth *= scaledFactor;
- }
-
- // underflow bin
- for (int i = 1; i < minValue; i++) {
- assertEquals(0, options.getBinForSample(i));
- }
-
- for (int i = 10; i < lastBinStartValue; i++) {
- assertTrue(options.getBinForSample(i) > 0);
- assertTrue(options.getBinForSample(i) <= binsCount);
- binCounts[options.getBinForSample(i) - 1]++;
- }
-
- // overflow bin
- assertEquals(binsCount + 1, options.getBinForSample(lastBinStartValue));
-
- for (int i = 1; i < binsCount; i++) {
- assertEquals(binCounts[i], binCounts[i - 1] * 2L);
- }
- }
-}
diff --git a/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java b/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java
deleted file mode 100644
index 037dbb3..0000000
--- a/core/tests/expresslog/src/com/android/internal/expresslog/UniformOptionsTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.internal.expresslog;
-
-import androidx.test.filters.SmallTest;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-@RunWith(JUnit4.class)
-@SmallTest
-public class UniformOptionsTest {
- private static final String TAG = UniformOptionsTest.class.getSimpleName();
-
- @Test
- public void testGetBinsCount() {
- Histogram.UniformOptions options1 = new Histogram.UniformOptions(1, 100, 1000);
- assertEquals(3, options1.getBinsCount());
-
- Histogram.UniformOptions options10 = new Histogram.UniformOptions(10, 100, 1000);
- assertEquals(12, options10.getBinsCount());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructZeroBinsCount() {
- new Histogram.UniformOptions(0, 100, 1000);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructNegativeBinsCount() {
- new Histogram.UniformOptions(-1, 100, 1000);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testConstructMaxValueLessThanMinValue() {
- new Histogram.UniformOptions(10, 1000, 100);
- }
-
- @Test
- public void testBinIndexForRangeEqual1() {
- Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 11);
- for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
- assertEquals(i, options.getBinForSample(i));
- }
- }
-
- @Test
- public void testBinIndexForRangeEqual2() {
- Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 21);
- for (int i = 0, bins = options.getBinsCount(); i < bins; i++) {
- assertEquals(i, options.getBinForSample(i * 2));
- assertEquals(i, options.getBinForSample(i * 2 - 1));
- }
- }
-
- @Test
- public void testBinIndexForRangeEqual5() {
- Histogram.UniformOptions options = new Histogram.UniformOptions(2, 0, 10);
- assertEquals(4, options.getBinsCount());
- for (int i = 0; i < 2; i++) {
- for (int sample = 0; sample < 5; sample++) {
- assertEquals(i + 1, options.getBinForSample(i * 5 + sample));
- }
- }
- }
-
- @Test
- public void testBinIndexForRangeEqual10() {
- Histogram.UniformOptions options = new Histogram.UniformOptions(10, 1, 101);
- assertEquals(0, options.getBinForSample(0));
- assertEquals(options.getBinsCount() - 2, options.getBinForSample(100));
- assertEquals(options.getBinsCount() - 1, options.getBinForSample(101));
-
- final float binSize = (101 - 1) / 10f;
- for (int i = 1, bins = options.getBinsCount() - 1; i < bins; i++) {
- assertEquals(i, options.getBinForSample(i * binSize));
- }
- }
-
- @Test
- public void testBinIndexForRangeEqual90() {
- final int binCount = 10;
- final int minValue = 100;
- final int maxValue = 100000;
-
- Histogram.UniformOptions options = new Histogram.UniformOptions(binCount, minValue,
- maxValue);
-
- // logging underflow sample
- assertEquals(0, options.getBinForSample(minValue - 1));
-
- // logging overflow sample
- assertEquals(binCount + 1, options.getBinForSample(maxValue));
- assertEquals(binCount + 1, options.getBinForSample(maxValue + 1));
-
- // logging min edge sample
- assertEquals(1, options.getBinForSample(minValue));
-
- // logging max edge sample
- assertEquals(binCount, options.getBinForSample(maxValue - 1));
-
- // logging single valid sample per bin
- final int binSize = (maxValue - minValue) / binCount;
-
- for (int i = 0; i < binCount; i++) {
- assertEquals(i + 1, options.getBinForSample(minValue + binSize * i));
- }
- }
-}
diff --git a/core/tests/fuzzers/ParcelFuzzer/Android.bp b/core/tests/fuzzers/ParcelFuzzer/Android.bp
index b71a06e..eff1985 100644
--- a/core/tests/fuzzers/ParcelFuzzer/Android.bp
+++ b/core/tests/fuzzers/ParcelFuzzer/Android.bp
@@ -34,6 +34,7 @@
"smoreland@google.com",
"waghpawan@google.com",
],
+ triage_assignee: "cobark@google.com", // TODO(b/280770893)
// Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer
hotlists: ["4637097"],
},
diff --git a/core/tests/fuzzers/java_service_fuzzer/Android.bp b/core/tests/fuzzers/java_service_fuzzer/Android.bp
index 6acb198..97538a5 100644
--- a/core/tests/fuzzers/java_service_fuzzer/Android.bp
+++ b/core/tests/fuzzers/java_service_fuzzer/Android.bp
@@ -42,6 +42,7 @@
"smoreland@google.com",
"waghpawan@google.com",
],
+ triage_assignee: "cobark@google.com", // TODO(b/261539788)
// Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer
hotlists: ["4637097"],
},
diff --git a/core/xsd/vts/OWNERS b/core/xsd/vts/OWNERS
new file mode 100644
index 0000000..9af2eba
--- /dev/null
+++ b/core/xsd/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 151862
+sundongahn@google.com
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
index d785c3c..f26b50e 100644
--- a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
+++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
@@ -21,10 +21,7 @@
import android.content.Context;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
-import android.os.RemoteException;
import android.os.ServiceManager;
-import android.security.GenerateRkpKey;
-import android.security.keymaster.KeymasterDefs;
class CredstoreIdentityCredentialStore extends IdentityCredentialStore {
@@ -125,18 +122,7 @@
@NonNull String docType) throws AlreadyPersonalizedException,
DocTypeNotSupportedException {
try {
- IWritableCredential wc;
- wc = mStore.createCredential(credentialName, docType);
- try {
- GenerateRkpKey keyGen = new GenerateRkpKey(mContext);
- // We don't know what the security level is for the backing keymint, so go ahead and
- // poke the provisioner for both TEE and SB.
- keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
- keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX);
- } catch (RemoteException e) {
- // Not really an error state. Does not apply at all if RKP is unsupported or
- // disabled on a given device.
- }
+ IWritableCredential wc = mStore.createCredential(credentialName, docType);
return new CredstoreWritableIdentityCredential(mContext, credentialName, docType, wc);
} catch (android.os.RemoteException e) {
throw new RuntimeException("Unexpected RemoteException ", e);
diff --git a/keystore/java/android/security/GenerateRkpKey.java b/keystore/java/android/security/GenerateRkpKey.java
deleted file mode 100644
index 6981332..0000000
--- a/keystore/java/android/security/GenerateRkpKey.java
+++ /dev/null
@@ -1,159 +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.security;
-
-import android.annotation.CheckResult;
-import android.annotation.IntDef;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-/**
- * GenerateKey is a helper class to handle interactions between Keystore and the RemoteProvisioner
- * app. There are two cases where Keystore should use this class.
- *
- * (1) : An app generates a new attested key pair, so Keystore calls notifyKeyGenerated to let the
- * RemoteProvisioner app check if the state of the attestation key pool is getting low enough
- * to warrant provisioning more attestation certificates early.
- *
- * (2) : An app attempts to generate a new key pair, but the keystore service discovers it is out of
- * attestation key pairs and cannot provide one for the given application. Keystore can then
- * make a blocking call on notifyEmpty to allow the RemoteProvisioner app to get another
- * attestation certificate chain provisioned.
- *
- * In most cases, the proper usage of (1) should preclude the need for (2).
- *
- * @hide
- */
-public class GenerateRkpKey {
- private static final String TAG = "GenerateRkpKey";
-
- private static final int NOTIFY_EMPTY = 0;
- private static final int NOTIFY_KEY_GENERATED = 1;
- private static final int TIMEOUT_MS = 1000;
-
- private IGenerateRkpKeyService mBinder;
- private Context mContext;
- private CountDownLatch mCountDownLatch;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(flag = true, value = {
- IGenerateRkpKeyService.Status.OK,
- IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY,
- IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR,
- IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED,
- IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR,
- IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR,
- IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR,
- IGenerateRkpKeyService.Status.INTERNAL_ERROR,
- })
- public @interface Status {
- }
-
- private ServiceConnection mConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- mBinder = IGenerateRkpKeyService.Stub.asInterface(service);
- mCountDownLatch.countDown();
- }
-
- @Override public void onBindingDied(ComponentName className) {
- mCountDownLatch.countDown();
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- mBinder = null;
- }
- };
-
- /**
- * Constructor which takes a Context object.
- */
- public GenerateRkpKey(Context context) {
- mContext = context;
- }
-
- @Status
- private int bindAndSendCommand(int command, int securityLevel) throws RemoteException {
- Intent intent = new Intent(IGenerateRkpKeyService.class.getName());
- ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
- int returnCode = IGenerateRkpKeyService.Status.OK;
- if (comp == null) {
- // On a system that does not use RKP, the RemoteProvisioner app won't be installed.
- return returnCode;
- }
- intent.setComponent(comp);
- mCountDownLatch = new CountDownLatch(1);
- Executor executor = Executors.newCachedThreadPool();
- if (!mContext.bindService(intent, Context.BIND_AUTO_CREATE, executor, mConnection)) {
- throw new RemoteException("Failed to bind to GenerateRkpKeyService");
- }
- try {
- mCountDownLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Interrupted: ", e);
- }
- if (mBinder != null) {
- switch (command) {
- case NOTIFY_EMPTY:
- returnCode = mBinder.generateKey(securityLevel);
- break;
- case NOTIFY_KEY_GENERATED:
- mBinder.notifyKeyGenerated(securityLevel);
- break;
- default:
- Log.e(TAG, "Invalid case for command");
- }
- } else {
- Log.e(TAG, "Binder object is null; failed to bind to GenerateRkpKeyService.");
- returnCode = IGenerateRkpKeyService.Status.INTERNAL_ERROR;
- }
- mContext.unbindService(mConnection);
- return returnCode;
- }
-
- /**
- * Fulfills the use case of (2) described in the class documentation. Blocks until the
- * RemoteProvisioner application can get new attestation keys signed by the server.
- * @return the status of the key generation
- */
- @CheckResult
- @Status
- public int notifyEmpty(int securityLevel) throws RemoteException {
- return bindAndSendCommand(NOTIFY_EMPTY, securityLevel);
- }
-
- /**
- * Fulfills the use case of (1) described in the class documentation. Non blocking call.
- */
- public void notifyKeyGenerated(int securityLevel) throws RemoteException {
- bindAndSendCommand(NOTIFY_KEY_GENERATED, securityLevel);
- }
-}
diff --git a/keystore/java/android/security/GenerateRkpKeyException.java b/keystore/java/android/security/GenerateRkpKeyException.java
deleted file mode 100644
index a2d65e4..0000000
--- a/keystore/java/android/security/GenerateRkpKeyException.java
+++ /dev/null
@@ -1,31 +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.security;
-
-/**
- * Thrown on problems in attempting to attest to a key using a remotely provisioned key.
- *
- * @hide
- */
-public class GenerateRkpKeyException extends Exception {
-
- /**
- * Constructs a new {@code GenerateRkpKeyException}.
- */
- public GenerateRkpKeyException() {
- }
-}
diff --git a/keystore/java/android/security/IGenerateRkpKeyService.aidl b/keystore/java/android/security/IGenerateRkpKeyService.aidl
deleted file mode 100644
index eeaeb27..0000000
--- a/keystore/java/android/security/IGenerateRkpKeyService.aidl
+++ /dev/null
@@ -1,60 +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.security;
-
-/**
- * Interface to allow the framework to notify the RemoteProvisioner app when keys are empty. This
- * will be used if Keystore replies with an error code NO_KEYS_AVAILABLE in response to an
- * attestation request. The framework can then synchronously call generateKey() to get more
- * attestation keys generated and signed. Upon return, the caller can be certain an attestation key
- * is available.
- *
- * @hide
- */
-interface IGenerateRkpKeyService {
- @JavaDerive(toString=true)
- @Backing(type="int")
- enum Status {
- /** No error(s) occurred */
- OK = 0,
- /** Unable to provision keys due to a lack of internet connectivity. */
- NO_NETWORK_CONNECTIVITY = 1,
- /** An error occurred while communicating with the RKP server. */
- NETWORK_COMMUNICATION_ERROR = 2,
- /** The given device was not registered with the RKP backend. */
- DEVICE_NOT_REGISTERED = 4,
- /** The RKP server returned an HTTP client error, indicating a misbehaving client. */
- HTTP_CLIENT_ERROR = 5,
- /** The RKP server returned an HTTP server error, indicating something went wrong on the server. */
- HTTP_SERVER_ERROR = 6,
- /** The RKP server returned an HTTP status that is unknown. This should never happen. */
- HTTP_UNKNOWN_ERROR = 7,
- /** An unexpected internal error occurred. This should never happen. */
- INTERNAL_ERROR = 8,
- }
-
- /**
- * Ping the provisioner service to let it know an app generated a key. This may or may not have
- * consumed a remotely provisioned attestation key, so the RemoteProvisioner app should check.
- */
- oneway void notifyKeyGenerated(in int securityLevel);
-
- /**
- * Ping the provisioner service to indicate there are no remaining attestation keys left.
- */
- Status generateKey(in int securityLevel);
-}
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index c2cd6ff..74597c5 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -161,6 +161,15 @@
}
/**
+ * List all entries in the keystore for in the given namespace.
+ */
+ public KeyDescriptor[] listBatch(int domain, long namespace, String startPastAlias)
+ throws KeyStoreException {
+ return handleRemoteExceptionWithRetry(
+ (service) -> service.listEntriesBatched(domain, namespace, startPastAlias));
+ }
+
+ /**
* Grant string prefix as used by the keystore boringssl engine. Must be kept in sync
* with system/security/keystore-engine. Note: The prefix here includes the 0x which
* std::stringstream used in keystore-engine needs to identify the number as hex represented.
@@ -301,6 +310,13 @@
});
}
+ /**
+ * Returns the number of Keystore entries for a given domain and namespace.
+ */
+ public int getNumberOfEntries(int domain, long namespace) throws KeyStoreException {
+ return handleRemoteExceptionWithRetry((service)
+ -> service.getNumberOfEntries(domain, namespace));
+ }
protected static void interruptedPreservingSleep(long millis) {
boolean wasInterrupted = false;
Calendar calendar = Calendar.getInstance();
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
index cb75779..253d704 100644
--- a/keystore/java/android/security/KeyStoreException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -614,9 +614,23 @@
KEYMINT_UNIMPLEMENTED_ERROR);
sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE,
KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_PROOF_OF_PRESENCE_REQUIRED,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CONCURRENT_PROOF_OF_PRESENCE_REQUESTED,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_NO_USER_CONFIRMATION,
+ KEYMINT_INCORRECT_USAGE_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_EARLY_BOOT_ENDED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_KEYS_NOT_PROVISIONED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_IDS_NOT_PROVISIONED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_OPERATION,
+ GENERAL_KEYMINT_ERROR);
sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_STORAGE_KEY_UNSUPPORTED,
KEYMINT_UNIMPLEMENTED_ERROR);
sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_MGF_DIGEST,
@@ -627,6 +641,12 @@
KEYMINT_INCORRECT_USAGE_ERROR);
sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_AFTER,
KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_ISSUER_SUBJECT,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_ISSUER_SUBJECT,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_BOOT_LEVEL_EXCEEDED,
+ 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);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index 7571e44..d129891 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -24,6 +24,7 @@
import android.security.KeyStoreOperation;
import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyStoreCryptoOperation;
+import android.system.keystore2.Authorization;
import libcore.util.EmptyArray;
@@ -119,6 +120,14 @@
mCipher = null;
}
+ private Authorization[] getKeyCharacteristics(Key key) {
+ if (!(key instanceof AndroidKeyStoreKey)) {
+ return new Authorization[] {};
+ }
+
+ return ((AndroidKeyStoreKey) key).getAuthorizations();
+ }
+
@Override
protected final void engineInit(int opmode, Key key, SecureRandom random)
throws InvalidKeyException {
@@ -173,7 +182,7 @@
init(opmode, key, random);
initAlgorithmSpecificParameters();
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(key));
} catch (InvalidAlgorithmParameterException e) {
throw new InvalidKeyException(e);
}
@@ -206,7 +215,7 @@
try {
init(opmode, key, random);
initAlgorithmSpecificParameters(params);
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(key));
success = true;
} finally {
if (!success) {
@@ -236,7 +245,7 @@
try {
init(opmode, key, random);
initAlgorithmSpecificParameters(params);
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(key));
success = true;
} finally {
if (!success) {
@@ -310,7 +319,8 @@
mCachedException = null;
}
- private void ensureKeystoreOperationInitialized() throws InvalidKeyException,
+ private void ensureKeystoreOperationInitialized(Authorization[] keyCharacteristics)
+ throws InvalidKeyException,
InvalidAlgorithmParameterException {
if (mMainDataStreamer != null) {
return;
@@ -323,7 +333,7 @@
}
List<KeyParameter> parameters = new ArrayList<>();
- addAlgorithmSpecificParametersToBegin(parameters);
+ addAlgorithmSpecificParametersToBegin(parameters, keyCharacteristics);
int purpose;
if (mKeymasterPurposeOverride != -1) {
@@ -404,7 +414,7 @@
return null;
}
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey));
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
mCachedException = e;
return null;
@@ -520,7 +530,7 @@
}
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey));
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
mCachedException = e;
return;
@@ -597,7 +607,7 @@
}
try {
- ensureKeystoreOperationInitialized();
+ ensureKeystoreOperationInitialized(getKeyCharacteristics(mKey));
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw (IllegalBlockSizeException) new IllegalBlockSizeException().initCause(e);
}
@@ -1012,6 +1022,22 @@
@NonNull List<KeyParameter> parameters);
/**
+ * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation,
+ * including the key characteristics. This is useful in case the parameters to {@code begin}
+ * depend on how the key was generated.
+ * The default implementation provided here simply ignores these key characteristics because
+ * they are not be needed for most engines.
+ *
+ * @param parameters keystore/keymaster arguments to be populated with algorithm-specific
+ * parameters.
+ * @param keyCharacteristics The key's characteristics.
+ */
+ protected void addAlgorithmSpecificParametersToBegin(
+ @NonNull List<KeyParameter> parameters, Authorization[] keyCharacteristics) {
+ addAlgorithmSpecificParametersToBegin(parameters);
+ }
+
+ /**
* Invoked to obtain algorithm-specific parameters from the result of the KeyStore's
* {@code begin} operation.
*
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index c3b0f9b..474b7ea 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -20,7 +20,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityThread;
import android.content.Context;
import android.hardware.security.keymint.EcCurve;
import android.hardware.security.keymint.KeyParameter;
@@ -28,9 +27,6 @@
import android.hardware.security.keymint.SecurityLevel;
import android.hardware.security.keymint.Tag;
import android.os.Build;
-import android.os.RemoteException;
-import android.security.GenerateRkpKey;
-import android.security.IGenerateRkpKeyService;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore2;
import android.security.KeyStoreException;
@@ -621,45 +617,6 @@
@Override
public KeyPair generateKeyPair() {
- GenerateKeyPairHelperResult result = new GenerateKeyPairHelperResult(0, null);
- for (int i = 0; i < 2; i++) {
- /**
- * NOTE: There is no need to delay between re-tries because the call to
- * GenerateRkpKey.notifyEmpty() will delay for a while before returning.
- */
- result = generateKeyPairHelper();
- if (result.rkpStatus == KeyStoreException.RKP_SUCCESS && result.keyPair != null) {
- return result.keyPair;
- }
- }
-
- // RKP failure
- if (result.rkpStatus != KeyStoreException.RKP_SUCCESS) {
- KeyStoreException ksException = new KeyStoreException(ResponseCode.OUT_OF_KEYS,
- "Could not get RKP keys", result.rkpStatus);
- throw new ProviderException("Failed to provision new attestation keys.", ksException);
- }
-
- return result.keyPair;
- }
-
- private static class GenerateKeyPairHelperResult {
- // Zero indicates success, non-zero indicates failure. Values should be
- // {@link android.security.KeyStoreException#RKP_TEMPORARILY_UNAVAILABLE},
- // {@link android.security.KeyStoreException#RKP_SERVER_REFUSED_ISSUANCE},
- // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_CONNECTIVITY}
- // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_SOFTWARE_REBOOT}
- public final int rkpStatus;
- @Nullable
- public final KeyPair keyPair;
-
- private GenerateKeyPairHelperResult(int rkpStatus, KeyPair keyPair) {
- this.rkpStatus = rkpStatus;
- this.keyPair = keyPair;
- }
- }
-
- private GenerateKeyPairHelperResult generateKeyPairHelper() {
if (mKeyStore == null || mSpec == null) {
throw new IllegalStateException("Not initialized");
}
@@ -697,26 +654,12 @@
AndroidKeyStorePublicKey publicKey =
AndroidKeyStoreProvider.makeAndroidKeyStorePublicKeyFromKeyEntryResponse(
descriptor, metadata, iSecurityLevel, mKeymasterAlgorithm);
- GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
- .currentApplication());
- try {
- if (mSpec.getAttestationChallenge() != null) {
- keyGen.notifyKeyGenerated(securityLevel);
- }
- } catch (RemoteException e) {
- // This is not really an error state, and necessarily does not apply to non RKP
- // systems or hybrid systems where RKP is not currently turned on.
- Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e);
- }
success = true;
- KeyPair kp = new KeyPair(publicKey, publicKey.getPrivateKey());
- return new GenerateKeyPairHelperResult(0, kp);
+ return new KeyPair(publicKey, publicKey.getPrivateKey());
} catch (KeyStoreException e) {
switch (e.getErrorCode()) {
case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE:
throw new StrongBoxUnavailableException("Failed to generated key pair.", e);
- case ResponseCode.OUT_OF_KEYS:
- return checkIfRetryableOrThrow(e, securityLevel);
default:
ProviderException p = new ProviderException("Failed to generate key pair.", e);
if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) {
@@ -742,55 +685,6 @@
}
}
- // In case keystore reports OUT_OF_KEYS, call this handler in an attempt to remotely provision
- // some keys.
- GenerateKeyPairHelperResult checkIfRetryableOrThrow(KeyStoreException e, int securityLevel) {
- GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
- .currentApplication());
- KeyStoreException ksException;
- try {
- final int keyGenStatus = keyGen.notifyEmpty(securityLevel);
- // Default stance: temporary error. This is a hint to the caller to try again with
- // exponential back-off.
- int rkpStatus;
- switch (keyGenStatus) {
- case IGenerateRkpKeyService.Status.NO_NETWORK_CONNECTIVITY:
- rkpStatus = KeyStoreException.RKP_FETCHING_PENDING_CONNECTIVITY;
- break;
- case IGenerateRkpKeyService.Status.DEVICE_NOT_REGISTERED:
- rkpStatus = KeyStoreException.RKP_SERVER_REFUSED_ISSUANCE;
- break;
- case IGenerateRkpKeyService.Status.OK:
- // Explicitly return not-OK here so we retry in generateKeyPair. All other cases
- // should throw because a retry doesn't make sense if we didn't actually
- // provision fresh keys.
- return new GenerateKeyPairHelperResult(
- KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE, null);
- case IGenerateRkpKeyService.Status.NETWORK_COMMUNICATION_ERROR:
- case IGenerateRkpKeyService.Status.HTTP_CLIENT_ERROR:
- case IGenerateRkpKeyService.Status.HTTP_SERVER_ERROR:
- case IGenerateRkpKeyService.Status.HTTP_UNKNOWN_ERROR:
- case IGenerateRkpKeyService.Status.INTERNAL_ERROR:
- default:
- // These errors really should never happen. The best we can do is assume they
- // are transient and hint to the caller to retry with back-off.
- rkpStatus = KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE;
- break;
- }
- ksException = new KeyStoreException(
- ResponseCode.OUT_OF_KEYS,
- "Out of RKP keys due to IGenerateRkpKeyService status: " + keyGenStatus,
- rkpStatus);
- } catch (RemoteException f) {
- ksException = new KeyStoreException(
- ResponseCode.OUT_OF_KEYS,
- "Remote exception: " + f.getMessage(),
- KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE);
- }
- ksException.initCause(e);
- throw new ProviderException("Failed to provision new attestation keys.", ksException);
- }
-
private void addAttestationParameters(@NonNull List<KeyParameter> params)
throws ProviderException, IllegalArgumentException, DeviceIdAttestationException {
byte[] challenge = mSpec.getAttestationChallenge();
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
index e9b66aa..3bb2564 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
@@ -288,16 +288,34 @@
}
}
+ private static boolean isMgfDigestTagPresentInKeyProperties(
+ Authorization[] keyCharacteristics) {
+ for (Authorization authorization : keyCharacteristics) {
+ if (authorization.keyParameter.tag == KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
@Override
protected final void addAlgorithmSpecificParametersToBegin(
- @NonNull List<KeyParameter> parameters) {
- super.addAlgorithmSpecificParametersToBegin(parameters);
+ @NonNull List<KeyParameter> parameters, Authorization[] keyCharacteristics) {
+ super.addAlgorithmSpecificParametersToBegin(parameters, keyCharacteristics);
parameters.add(KeyStore2ParameterUtils.makeEnum(
KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest
));
- parameters.add(KeyStore2ParameterUtils.makeEnum(
- KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest
- ));
+ // Only add the KM_TAG_RSA_OAEP_MGF_DIGEST tag to begin() if the MGF Digest is
+ // present in the key properties. Keys generated prior to Android 14 did not have
+ // this tag (Keystore didn't add it) so specifying any MGF digest tag would cause
+ // a begin() operation (on an Android 14 device) to fail (with a key that was generated
+ // on Android 13 or below).
+ if (isMgfDigestTagPresentInKeyProperties(keyCharacteristics)) {
+ parameters.add(KeyStore2ParameterUtils.makeEnum(
+ KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest
+ ));
+ }
}
@Override
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index 91f216f..045e318 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -79,13 +79,11 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
+import java.util.NoSuchElementException;
import javax.crypto.SecretKey;
@@ -1043,26 +1041,22 @@
}
}
- private Set<String> getUniqueAliases() {
+ private KeyDescriptor[] getAliasesBatch(String startPastAlias) {
try {
- final KeyDescriptor[] keys = mKeyStore.list(
+ return mKeyStore.listBatch(
getTargetDomain(),
- mNamespace
+ mNamespace,
+ startPastAlias
);
- final Set<String> aliases = new HashSet<>(keys.length);
- for (KeyDescriptor d : keys) {
- aliases.add(d.alias);
- }
- return aliases;
} catch (android.security.KeyStoreException e) {
Log.e(TAG, "Failed to list keystore entries.", e);
- return new HashSet<>();
+ return new KeyDescriptor[0];
}
}
@Override
public Enumeration<String> engineAliases() {
- return Collections.enumeration(getUniqueAliases());
+ return new KeyEntriesEnumerator();
}
@Override
@@ -1073,12 +1067,18 @@
return getKeyMetadata(alias) != null;
}
-
@Override
public int engineSize() {
- return getUniqueAliases().size();
+ try {
+ return mKeyStore.getNumberOfEntries(
+ getTargetDomain(),
+ mNamespace
+ );
+ } catch (android.security.KeyStoreException e) {
+ Log.e(TAG, "Failed to get the number of keystore entries.", e);
+ return 0;
+ }
}
-
@Override
public boolean engineIsKeyEntry(String alias) {
return isKeyEntry(alias);
@@ -1251,4 +1251,38 @@
+ "or TrustedCertificateEntry; was " + entry);
}
}
+
+ private class KeyEntriesEnumerator implements Enumeration<String> {
+ private KeyDescriptor[] mCurrentBatch;
+ private int mCurrentEntry = 0;
+ private String mLastAlias = null;
+ private KeyEntriesEnumerator() {
+ getAndValidateNextBatch();
+ }
+
+ private void getAndValidateNextBatch() {
+ mCurrentBatch = getAliasesBatch(mLastAlias);
+ mCurrentEntry = 0;
+ }
+
+ public boolean hasMoreElements() {
+ return (mCurrentBatch != null) && (mCurrentBatch.length > 0);
+ }
+
+ public String nextElement() {
+ if ((mCurrentBatch == null) || (mCurrentBatch.length == 0)) {
+ throw new NoSuchElementException("Error while fetching entries.");
+ }
+ final KeyDescriptor currentEntry = mCurrentBatch[mCurrentEntry];
+ mLastAlias = currentEntry.alias;
+
+ mCurrentEntry++;
+ // This was the last entry in the batch.
+ if (mCurrentEntry >= mCurrentBatch.length) {
+ getAndValidateNextBatch();
+ }
+
+ return mLastAlias;
+ }
+ }
}
diff --git a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
index f96c39c8..1e1f68a 100644
--- a/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
+++ b/keystore/tests/src/android/security/keystore2/AndroidKeyStoreSpiTest.java
@@ -17,9 +17,14 @@
package android.security.keystore2;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.isNull;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.security.KeyStore2;
@@ -36,6 +41,12 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.NoSuchElementException;
+
public class AndroidKeyStoreSpiTest {
@Mock
@@ -48,14 +59,176 @@
@Test
public void testEngineAliasesReturnsEmptySetOnKeyStoreError() throws Exception {
- when(mKeystore2.list(anyInt(), anyLong()))
+ when(mKeystore2.listBatch(anyInt(), anyLong(), isNull()))
.thenThrow(new KeyStoreException(6, "Some Error"));
AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
spi.initForTesting(mKeystore2);
assertThat("Empty collection expected", !spi.engineAliases().hasMoreElements());
- verify(mKeystore2).list(anyInt(), anyLong());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), isNull());
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsZeroEntriesEmptyArray() throws Exception {
+ when(mKeystore2.listBatch(anyInt(), anyLong(), anyString()))
+ .thenReturn(new KeyDescriptor[0]);
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ Enumeration<String> aliases = spi.engineAliases();
+ assertThat("Should not have any elements", !aliases.hasMoreElements());
+ assertThrows("Should have no elements to return", NoSuchElementException.class,
+ () -> aliases.nextElement());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), isNull());
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsZeroEntriesNullArray() throws Exception {
+ when(mKeystore2.listBatch(anyInt(), anyLong(), anyString()))
+ .thenReturn(null);
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ Enumeration<String> aliases = spi.engineAliases();
+ assertThat("Should not have any elements", !aliases.hasMoreElements());
+ assertThrows("Should have no elements to return", NoSuchElementException.class,
+ () -> aliases.nextElement());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), isNull());
+ }
+
+ private static KeyDescriptor newKeyDescriptor(String alias) {
+ KeyDescriptor result = new KeyDescriptor();
+ result.alias = alias;
+ return result;
+ }
+
+ private static KeyDescriptor[] createKeyDescriptorsArray(int numEntries) {
+ KeyDescriptor[] kds = new KeyDescriptor[numEntries];
+ for (int i = 0; i < kds.length; i++) {
+ kds[i] = newKeyDescriptor(String.format("alias-%d", i));
+ }
+
+ return kds;
+ }
+
+ private static void assertAliasListsEqual(
+ KeyDescriptor[] keyDescriptors, Enumeration<String> aliasesEnumerator) {
+ List<String> aliases = Collections.list(aliasesEnumerator);
+ Assert.assertArrayEquals(Arrays.stream(keyDescriptors).map(kd -> kd.alias).toArray(),
+ aliases.toArray());
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesInASingleBatch() throws Exception {
+ final String alias1 = "testAlias1";
+ final String alias2 = "testAlias2";
+ final String alias3 = "testAlias3";
+ KeyDescriptor[] kds = {newKeyDescriptor(alias1),
+ newKeyDescriptor(alias2), newKeyDescriptor(alias3)};
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(kds);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("testAlias3")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ Enumeration<String> aliases = spi.engineAliases();
+ assertThat("Should have more elements before first.", aliases.hasMoreElements());
+ Assert.assertEquals(aliases.nextElement(), alias1);
+ assertThat("Should have more elements before second.", aliases.hasMoreElements());
+ Assert.assertEquals(aliases.nextElement(), alias2);
+ assertThat("Should have more elements before third.", aliases.hasMoreElements());
+ Assert.assertEquals(aliases.nextElement(), alias3);
+ assertThat("Should have no more elements after third.", !aliases.hasMoreElements());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("testAlias3"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesInMultipleBatches() throws Exception {
+ final int numEntries = 2500;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(Arrays.copyOfRange(kds, 0, 1000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-999")))
+ .thenReturn(Arrays.copyOfRange(kds, 1000, 2000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-1999")))
+ .thenReturn(Arrays.copyOfRange(kds, 2000, 2500));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-2499")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-999"));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-1999"));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-2499"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesWhenNumEntriesIsExactlyOneBatchSize()
+ throws Exception {
+ final int numEntries = 1000;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(kds);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-999")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-999"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesWhenNumEntriesIsAMultiplyOfBatchSize()
+ throws Exception {
+ final int numEntries = 2000;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(Arrays.copyOfRange(kds, 0, 1000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-999")))
+ .thenReturn(Arrays.copyOfRange(kds, 1000, 2000));
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-1999")))
+ .thenReturn(null);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-999"));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-1999"));
+ verifyNoMoreInteractions(mKeystore2);
+ }
+
+ @Test
+ public void testEngineAliasesCorrectlyListsEntriesWhenReturningLessThanBatchSize()
+ throws Exception {
+ final int numEntries = 500;
+ KeyDescriptor[] kds = createKeyDescriptorsArray(numEntries);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq(null)))
+ .thenReturn(kds);
+ when(mKeystore2.listBatch(anyInt(), anyLong(), eq("alias-499")))
+ .thenReturn(new KeyDescriptor[0]);
+
+ AndroidKeyStoreSpi spi = new AndroidKeyStoreSpi();
+ spi.initForTesting(mKeystore2);
+
+ assertAliasListsEqual(kds, spi.engineAliases());
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq(null));
+ verify(mKeystore2).listBatch(anyInt(), anyLong(), eq("alias-499"));
+ verifyNoMoreInteractions(mKeystore2);
}
@Mock
diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS
index 852edef..f0ed6ee 100644
--- a/libs/WindowManager/Shell/OWNERS
+++ b/libs/WindowManager/Shell/OWNERS
@@ -1,4 +1,4 @@
xutan@google.com
# Give submodule owners in shell resource approval
-per-file res*/*/*.xml = hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com
+per-file res*/*/*.xml = atsjenk@google.com, hwwang@google.com, jorgegil@google.com, lbill@google.com, madym@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
index 926cfb3..deb7c6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/OWNERS
@@ -1,2 +1,3 @@
# WM shell sub-module desktop owners
+atsjenk@google.com
madym@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
index 0c2d5c4..a3803ed 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/OWNERS
@@ -1,2 +1,4 @@
# WM shell sub-module freeform owners
+atsjenk@google.com
+jorgegil@google.com
madym@google.com
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index 1c28c3d..deebad5 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -7,3 +7,5 @@
madym@google.com
hwwang@google.com
chenghsiuchang@google.com
+atsjenk@google.com
+jorgegil@google.com
diff --git a/libs/androidfw/include/androidfw/ObbFile.h b/libs/androidfw/include/androidfw/ObbFile.h
index 3dbf997d..38ece5c1 100644
--- a/libs/androidfw/include/androidfw/ObbFile.h
+++ b/libs/androidfw/include/androidfw/ObbFile.h
@@ -43,10 +43,6 @@
bool removeFrom(const char* filename);
bool removeFrom(int fd);
- const char* getFileName() const {
- return mFileName;
- }
-
const String8 getPackageName() const {
return mPackageName;
}
@@ -127,8 +123,6 @@
/* The encryption salt. */
unsigned char mSalt[8];
- const char* mFileName;
-
size_t mFooterStart;
bool parseObbFile(int fd);
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 979a660..8f022ac 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -55,6 +55,10 @@
// GCC false-positives on this warning, and since we -Werror that's
// a problem
"-Wno-free-nonheap-object",
+
+ // Do not de-optimise cold code paths in AFDO.
+ // Some code paths might be infrequently executed but critical to latency.
+ "-fno-profile-sample-accurate",
],
include_dirs: [
@@ -722,6 +726,9 @@
"tests/unit/VectorDrawableTests.cpp",
"tests/unit/WebViewFunctorManagerTests.cpp",
],
+ data: [
+ ":hwuimicro",
+ ],
}
// ------------------------
diff --git a/libs/hwui/AndroidTest.xml b/libs/hwui/AndroidTest.xml
index 911315f..75f61f5 100644
--- a/libs/hwui/AndroidTest.xml
+++ b/libs/hwui/AndroidTest.xml
@@ -21,6 +21,7 @@
<option name="push" value="hwuimacro->/data/local/tmp/benchmarktest/hwuimacro" />
</target_preparer>
<option name="test-suite-tag" value="apct" />
+ <option name="not-shardable" value="true" />
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp/nativetest" />
<option name="module-name" value="hwui_unit_tests" />
diff --git a/libs/hwui/jni/FontFamily.cpp b/libs/hwui/jni/FontFamily.cpp
index ce5ac38..f632d09 100644
--- a/libs/hwui/jni/FontFamily.cpp
+++ b/libs/hwui/jni/FontFamily.cpp
@@ -44,6 +44,7 @@
namespace android {
+namespace {
struct NativeFamilyBuilder {
NativeFamilyBuilder(uint32_t langId, int variant)
: langId(langId), variant(static_cast<minikin::FamilyVariant>(variant)) {}
@@ -52,6 +53,7 @@
std::vector<std::shared_ptr<minikin::Font>> fonts;
std::vector<minikin::FontVariation> axes;
};
+} // namespace
static inline NativeFamilyBuilder* toNativeBuilder(jlong ptr) {
return reinterpret_cast<NativeFamilyBuilder*>(ptr);
diff --git a/libs/hwui/jni/fonts/FontFamily.cpp b/libs/hwui/jni/fonts/FontFamily.cpp
index b682135..ac1c05e 100644
--- a/libs/hwui/jni/fonts/FontFamily.cpp
+++ b/libs/hwui/jni/fonts/FontFamily.cpp
@@ -29,9 +29,11 @@
namespace android {
+namespace {
struct NativeFamilyBuilder {
std::vector<std::shared_ptr<minikin::Font>> fonts;
};
+} // namespace
static inline NativeFamilyBuilder* toBuilder(jlong ptr) {
return reinterpret_cast<NativeFamilyBuilder*>(ptr);
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 8e350d5..b5c1b49 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -53,6 +53,8 @@
}
MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
+ bool wasSurfaceless = mEglManager.isCurrent(EGL_NO_SURFACE);
+
// In case the surface was destroyed (e.g. a previous trimMemory call) we
// need to recreate it here.
if (!isSurfaceReady() && mNativeWindow) {
@@ -63,6 +65,40 @@
if (!mEglManager.makeCurrent(mEglSurface, &error)) {
return MakeCurrentResult::AlreadyCurrent;
}
+
+ EGLint majorVersion = 0;
+ eglQueryContext(eglGetCurrentDisplay(), eglGetCurrentContext(), EGL_CONTEXT_CLIENT_VERSION, &majorVersion);
+
+ // Make sure read/draw buffer state of default framebuffer is GL_BACK for ES 3.X. Vendor implementations
+ // disagree on the draw/read buffer state if the default framebuffer transitions from a surface
+ // to EGL_NO_SURFACE and vice-versa. There was a related discussion within Khronos on this topic.
+ // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13534.
+ // The discussion was not resolved with a clear consensus
+ if (error == 0 && (majorVersion > 2) && wasSurfaceless && mEglSurface != EGL_NO_SURFACE) {
+ GLint curReadFB = 0;
+ GLint curDrawFB = 0;
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &curReadFB);
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curDrawFB);
+
+ GLint buffer = GL_NONE;
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glGetIntegerv(GL_DRAW_BUFFER0, &buffer);
+ if (buffer == GL_NONE) {
+ const GLenum drawBuffer = GL_BACK;
+ glDrawBuffers(1, &drawBuffer);
+ }
+
+ glGetIntegerv(GL_READ_BUFFER, &buffer);
+ if (buffer == GL_NONE) {
+ glReadBuffer(GL_BACK);
+ }
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, curReadFB);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, curDrawFB);
+
+ GL_CHECKPOINT(LOW);
+ }
+
return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded;
}
diff --git a/media/OWNERS b/media/OWNERS
index 5f50137..4a6648e 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,4 +1,5 @@
# Bug component: 1344
+atneya@google.com
elaurent@google.com
essick@google.com
etalvala@google.com
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 23ee505..6e1fec2 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -12,16 +12,16 @@
]
},
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
],
"file_patterns": ["(?i)drm|crypto"]
diff --git a/media/aidl/android/media/soundtrigger_middleware/OWNERS b/media/aidl/android/media/soundtrigger_middleware/OWNERS
index 01b2cb9..1e41886 100644
--- a/media/aidl/android/media/soundtrigger_middleware/OWNERS
+++ b/media/aidl/android/media/soundtrigger_middleware/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 22033c6..6b29fc3 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -72,7 +72,7 @@
throw new UnsupportedOperationException("Trying to instantiate AudioSystem");
}
- /* These values must be kept in sync with system/audio.h */
+ /* These values must be kept in sync with system/media/audio/include/system/audio-hal-enums.h */
/*
* If these are modified, please also update Settings.System.VOLUME_SETTINGS
* and attrs.xml and AudioManager.java.
@@ -963,7 +963,8 @@
*/
//
- // audio device definitions: must be kept in sync with values in system/core/audio.h
+ // audio device definitions: must be kept in sync with values
+ // in system/media/audio/include/system/audio-hal-enums.h
//
/** @hide */
public static final int DEVICE_NONE = 0x0;
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index f85bdee..094a33f 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -25,6 +25,8 @@
import android.media.AudioSystem;
import android.os.Build;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
@@ -252,10 +254,10 @@
if (o == null || getClass() != o.getClass()) return false;
final AudioMix that = (AudioMix) o;
- return (this.mRouteFlags == that.mRouteFlags)
- && (this.mRule == that.mRule)
- && (this.mMixType == that.mMixType)
- && (this.mFormat == that.mFormat);
+ return Objects.equals(this.mRouteFlags, that.mRouteFlags)
+ && Objects.equals(this.mRule, that.mRule)
+ && Objects.equals(this.mMixType, that.mMixType)
+ && Objects.equals(this.mFormat, that.mFormat);
}
/** @hide */
@@ -340,7 +342,8 @@
* @param address
* @return the same Builder instance.
*/
- Builder setDevice(int deviceType, String address) {
+ @VisibleForTesting
+ public Builder setDevice(int deviceType, String address) {
mDeviceSystemType = deviceType;
mDeviceAddress = address;
return this;
diff --git a/media/java/android/media/musicrecognition/OWNERS b/media/java/android/media/musicrecognition/OWNERS
index 58f5d40..037b048 100644
--- a/media/java/android/media/musicrecognition/OWNERS
+++ b/media/java/android/media/musicrecognition/OWNERS
@@ -1,6 +1,5 @@
# Bug component: 830636
-joannechung@google.com
oni@google.com
volnov@google.com
diff --git a/media/java/android/media/soundtrigger/OWNERS b/media/java/android/media/soundtrigger/OWNERS
index 01b2cb9..85f7a4d 100644
--- a/media/java/android/media/soundtrigger/OWNERS
+++ b/media/java/android/media/soundtrigger/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 48436
atneya@google.com
elaurent@google.com
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 5b0c2a2..b878bcf5 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -43,6 +43,8 @@
#include <android_runtime/android_hardware_HardwareBuffer.h>
+#include <android-base/stringprintf.h>
+
#include <binder/MemoryDealer.h>
#include <cutils/compiler.h>
@@ -1099,7 +1101,8 @@
ALOGE("Could not create MediaCodec.BufferInfo.");
env->ExceptionClear();
}
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Fatal error: could not create MediaCodec.BufferInfo object");
return;
}
@@ -1121,7 +1124,8 @@
ALOGE("Could not create CodecException object.");
env->ExceptionClear();
}
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Fatal error: could not create CodecException object");
return;
}
@@ -1134,7 +1138,9 @@
CHECK(msg->findMessage("format", &format));
if (OK != ConvertMessageToMap(env, format, &obj)) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Fatal error: failed to convert format "
+ "from native to Java object");
return;
}
@@ -1166,7 +1172,8 @@
status_t err = ConvertMessageToMap(env, data, &obj);
if (err != OK) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Fatal error: failed to convert format from native to Java object");
return;
}
@@ -1187,7 +1194,8 @@
status_t err = ConvertMessageToMap(env, data, &obj);
if (err != OK) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Fatal error: failed to convert format from native to Java object");
return;
}
@@ -1198,6 +1206,18 @@
env->DeleteLocalRef(obj);
}
+std::string JMediaCodec::getExceptionMessage(const char *msg = nullptr) const {
+ if (mCodec == nullptr) {
+ return msg ?: "";
+ }
+ std::string prefix = "";
+ if (msg && msg[0] != '\0') {
+ prefix.append(msg);
+ prefix.append("\n");
+ }
+ return prefix + mCodec->getErrorLog().extract();
+}
+
void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatCallbackNotify:
@@ -1347,9 +1367,17 @@
env->Throw(exception);
}
+static std::string GetExceptionMessage(const sp<JMediaCodec> &codec, const char *msg) {
+ if (codec == NULL) {
+ return msg ?: "codec is released already";
+ }
+ return codec->getExceptionMessage(msg);
+}
+
static jint throwExceptionAsNecessary(
JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
- const char *msg = NULL, const sp<ICrypto>& crypto = NULL) {
+ const char *msg = NULL, const sp<ICrypto>& crypto = NULL,
+ const sp<JMediaCodec> &codec = NULL) {
switch (err) {
case OK:
return 0;
@@ -1364,23 +1392,38 @@
return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
case INVALID_OPERATION:
- jniThrowException(env, "java/lang/IllegalStateException", msg);
+ jniThrowException(
+ env, "java/lang/IllegalStateException",
+ GetExceptionMessage(codec, msg).c_str());
return 0;
case BAD_VALUE:
- jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+ jniThrowException(
+ env, "java/lang/IllegalArgumentException",
+ GetExceptionMessage(codec, msg).c_str());
return 0;
default:
if (isCryptoError(err)) {
- throwCryptoException(env, err, msg, crypto);
+ throwCryptoException(
+ env, err,
+ GetExceptionMessage(codec, msg).c_str(),
+ crypto);
return 0;
}
- throwCodecException(env, err, actionCode, msg);
+ throwCodecException(
+ env, err, actionCode,
+ GetExceptionMessage(codec, msg).c_str());
return 0;
}
}
+static jint throwExceptionAsNecessary(
+ JNIEnv *env, status_t err, const sp<JMediaCodec> &codec,
+ int32_t actionCode = ACTION_CODE_FATAL) {
+ return throwExceptionAsNecessary(env, err, actionCode, NULL, NULL, codec);
+}
+
static void android_media_MediaCodec_native_enableOnFirstTunnelFrameReadyListener(
JNIEnv *env,
jobject thiz,
@@ -1388,13 +1431,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->enableOnFirstTunnelFrameReadyListener(enabled);
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
@@ -1404,13 +1447,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->enableOnFrameRenderedListener(enabled);
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_setCallback(
@@ -1420,13 +1463,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->setCallback(cb);
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_configure(
@@ -1440,7 +1483,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1478,7 +1521,7 @@
err = codec->configure(format, bufferProducer, crypto, descrambler, flags);
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_native_setSurface(
@@ -1488,7 +1531,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1507,7 +1550,7 @@
}
status_t err = codec->setSurface(bufferProducer);
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
sp<PersistentSurface> android_media_MediaCodec_getPersistentInputSurface(
@@ -1611,7 +1654,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1625,7 +1668,7 @@
}
status_t err = codec->setInputSurface(persistentSurface);
if (err != NO_ERROR) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
}
@@ -1635,7 +1678,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -1643,7 +1686,7 @@
sp<IGraphicBufferProducer> bufferProducer;
status_t err = codec->createInputSurface(&bufferProducer);
if (err != NO_ERROR) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -1658,13 +1701,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->start();
- throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed");
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
@@ -1673,13 +1716,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->stop();
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
@@ -1688,7 +1731,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1701,7 +1744,7 @@
// trigger an IllegalStateException.
err = UNKNOWN_ERROR;
}
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
@@ -1710,13 +1753,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->flush();
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_queueInputBuffer(
@@ -1732,7 +1775,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1742,7 +1785,8 @@
index, offset, size, timestampUs, flags, &errorDetailMsg);
throwExceptionAsNecessary(
- env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
+ env, err, ACTION_CODE_FATAL,
+ codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
}
struct NativeCryptoInfo {
@@ -1766,7 +1810,9 @@
} else if (jmode == gCryptoModes.AesCbc) {
mMode = CryptoPlugin::kMode_AES_CBC;
} else {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(
+ env, INVALID_OPERATION, ACTION_CODE_FATAL,
+ base::StringPrintf("unrecognized crypto mode: %d", jmode).c_str());
return;
}
@@ -1902,7 +1948,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -1932,7 +1978,9 @@
} else if (jmode == gCryptoModes.AesCbc) {
mode = CryptoPlugin::kMode_AES_CBC;
} else {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(
+ env, INVALID_OPERATION, ACTION_CODE_FATAL,
+ base::StringPrintf("Unrecognized crypto mode: %d", jmode).c_str());
return;
}
@@ -2051,8 +2099,8 @@
subSamples = NULL;
throwExceptionAsNecessary(
- env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str(),
- codec->getCrypto());
+ env, err, ACTION_CODE_FATAL,
+ codec->getExceptionMessage(errorDetailMsg.c_str()).c_str(), codec->getCrypto());
}
static jobject android_media_MediaCodec_mapHardwareBuffer(JNIEnv *env, jclass, jobject bufferObj) {
@@ -2394,14 +2442,16 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == nullptr || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
sp<AMessage> tunings;
status_t err = ConvertKeyValueListsToAMessage(env, keys, values, &tunings);
if (err != OK) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(
+ env, err, ACTION_CODE_FATAL,
+ "error occurred while converting tunings from Java to native");
return;
}
@@ -2421,15 +2471,23 @@
}
env->MonitorExit(lock.get());
} else {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(
+ env, INVALID_OPERATION, ACTION_CODE_FATAL,
+ "Failed to grab lock for a LinearBlock object");
return;
}
AString errorDetailMsg;
if (codec->hasCryptoOrDescrambler()) {
if (!memory) {
+ // It means there was an unexpected failure in extractMemoryFromContext above
ALOGI("queueLinearBlock: no ashmem memory for encrypted content");
- throwExceptionAsNecessary(env, BAD_VALUE);
+ throwExceptionAsNecessary(
+ env, BAD_VALUE, ACTION_CODE_FATAL,
+ "Unexpected error: the input buffer is not compatible with "
+ "the secure codec, and a fallback logic failed.\n"
+ "Suggestion: please try including the secure codec when calling "
+ "MediaCodec.LinearBlock#obtain method to obtain a compatible buffer.");
return;
}
auto cryptoInfo =
@@ -2453,14 +2511,22 @@
ALOGI_IF(err != OK, "queueEncryptedLinearBlock returned err = %d", err);
} else {
if (!buffer) {
+ // It means there was an unexpected failure in extractBufferFromContext above
ALOGI("queueLinearBlock: no C2Buffer found");
- throwExceptionAsNecessary(env, BAD_VALUE);
+ throwExceptionAsNecessary(
+ env, BAD_VALUE, ACTION_CODE_FATAL,
+ "Unexpected error: the input buffer is not compatible with "
+ "the non-secure codec, and a fallback logic failed.\n"
+ "Suggestion: please do not include the secure codec when calling "
+ "MediaCodec.LinearBlock#obtain method to obtain a compatible buffer.");
return;
}
err = codec->queueBuffer(
index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
}
- throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, errorDetailMsg.c_str());
+ throwExceptionAsNecessary(
+ env, err, ACTION_CODE_FATAL,
+ codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
}
static void android_media_MediaCodec_native_queueHardwareBuffer(
@@ -2471,14 +2537,16 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
sp<AMessage> tunings;
status_t err = ConvertKeyValueListsToAMessage(env, keys, values, &tunings);
if (err != OK) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(
+ env, err, ACTION_CODE_FATAL,
+ "error occurred while converting tunings from Java to native");
return;
}
@@ -2503,7 +2571,9 @@
ALOGW("Failed to wrap AHardwareBuffer into C2GraphicAllocation");
native_handle_close(handle);
native_handle_delete(handle);
- throwExceptionAsNecessary(env, BAD_VALUE);
+ throwExceptionAsNecessary(
+ env, BAD_VALUE, ACTION_CODE_FATAL,
+ "HardwareBuffer not recognized");
return;
}
std::shared_ptr<C2GraphicBlock> block = _C2BlockFactory::CreateGraphicBlock(alloc);
@@ -2512,7 +2582,9 @@
AString errorDetailMsg;
err = codec->queueBuffer(
index, buffer, presentationTimeUs, flags, tunings, &errorDetailMsg);
- throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, errorDetailMsg.c_str());
+ throwExceptionAsNecessary(
+ env, err, ACTION_CODE_FATAL,
+ codec->getExceptionMessage(errorDetailMsg.c_str()).c_str());
}
static void android_media_MediaCodec_native_getOutputFrame(
@@ -2522,13 +2594,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->getOutputFrame(env, frame, index);
if (err != OK) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
}
@@ -2539,7 +2611,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return -1;
}
@@ -2550,7 +2622,7 @@
return (jint) index;
}
- return throwExceptionAsNecessary(env, err);
+ return throwExceptionAsNecessary(env, err, codec);
}
static jint android_media_MediaCodec_dequeueOutputBuffer(
@@ -2560,7 +2632,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return 0;
}
@@ -2572,7 +2644,7 @@
return (jint) index;
}
- return throwExceptionAsNecessary(env, err);
+ return throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_releaseOutputBuffer(
@@ -2583,13 +2655,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
@@ -2598,13 +2670,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t err = codec->signalEndOfInputStream();
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static jobject android_media_MediaCodec_getFormatNative(
@@ -2614,7 +2686,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2625,7 +2697,7 @@
return format;
}
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2637,7 +2709,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2648,7 +2720,7 @@
return format;
}
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2660,7 +2732,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2673,7 +2745,7 @@
// if we're out of memory, an exception was already thrown
if (err != NO_MEMORY) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
return NULL;
@@ -2686,7 +2758,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2699,7 +2771,7 @@
// if we're out of memory, an exception was already thrown
if (err != NO_MEMORY) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
return NULL;
@@ -2712,7 +2784,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2725,7 +2797,7 @@
// if we're out of memory, an exception was already thrown
if (err != NO_MEMORY) {
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
return NULL;
@@ -2738,7 +2810,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2749,7 +2821,7 @@
return name;
}
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2761,7 +2833,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2772,7 +2844,7 @@
return codecInfoObj;
}
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
return NULL;
}
@@ -2784,7 +2856,8 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ jniThrowException(env, "java/lang/IllegalStateException",
+ GetExceptionMessage(codec, NULL).c_str());
return 0;
}
@@ -2813,7 +2886,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -2824,7 +2897,7 @@
err = codec->setParameters(params);
}
- throwExceptionAsNecessary(env, err);
+ throwExceptionAsNecessary(env, err, codec);
}
static void android_media_MediaCodec_setVideoScalingMode(
@@ -2832,13 +2905,14 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
&& mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
- jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ String8::format("Unrecognized mode: %d", mode));
return;
}
@@ -2850,7 +2924,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
@@ -2862,14 +2936,14 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
jobject ret = NULL;
status_t status = codec->querySupportedVendorParameters(env, &ret);
if (status != OK) {
- throwExceptionAsNecessary(env, status);
+ throwExceptionAsNecessary(env, status, codec);
}
return ret;
@@ -2880,7 +2954,7 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return NULL;
}
@@ -2897,13 +2971,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t status = codec->subscribeToVendorParameters(env, names);
if (status != OK) {
- throwExceptionAsNecessary(env, status);
+ throwExceptionAsNecessary(env, status, codec);
}
return;
}
@@ -2913,13 +2987,13 @@
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
if (codec == NULL || codec->initCheck() != OK) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(env, INVALID_OPERATION, codec);
return;
}
status_t status = codec->unsubscribeFromVendorParameters(env, names);
if (status != OK) {
- throwExceptionAsNecessary(env, status);
+ throwExceptionAsNecessary(env, status, codec);
}
return;
}
@@ -3310,11 +3384,15 @@
if (!context->mReadonlyMapping) {
const C2BufferData data = buffer->data();
if (data.type() != C2BufferData::LINEAR) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(
+ env, INVALID_OPERATION, ACTION_CODE_FATAL,
+ "Underlying buffer is not a linear buffer");
return nullptr;
}
if (data.linearBlocks().size() != 1u) {
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(
+ env, INVALID_OPERATION, ACTION_CODE_FATAL,
+ "Underlying buffer contains more than one block");
return nullptr;
}
C2ConstLinearBlock block = data.linearBlocks().front();
@@ -3362,7 +3440,9 @@
false, // readOnly
true /* clearBuffer */);
}
- throwExceptionAsNecessary(env, INVALID_OPERATION);
+ throwExceptionAsNecessary(
+ env, INVALID_OPERATION, ACTION_CODE_FATAL,
+ "Underlying buffer is empty");
return nullptr;
}
@@ -3385,7 +3465,9 @@
}
const char *cstr = env->GetStringUTFChars(jstr, nullptr);
if (cstr == nullptr) {
- throwExceptionAsNecessary(env, BAD_VALUE);
+ throwExceptionAsNecessary(
+ env, BAD_VALUE, ACTION_CODE_FATAL,
+ "Error converting Java string to native");
return;
}
names->emplace_back(cstr);
@@ -3437,6 +3519,7 @@
}
status_t err = MediaCodec::CanFetchLinearBlock(names, &isCompatible);
if (err != OK) {
+ // TODO: CodecErrorLog
throwExceptionAsNecessary(env, err);
}
return isCompatible;
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 616c31b..fbaf64f 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -176,6 +176,8 @@
const sp<ICrypto> &getCrypto() { return mCrypto; }
+ std::string getExceptionMessage(const char *msg) const;
+
protected:
virtual ~JMediaCodec();
diff --git a/media/jni/android_media_MediaCodecLinearBlock.h b/media/jni/android_media_MediaCodecLinearBlock.h
index c753020..060abfd 100644
--- a/media/jni/android_media_MediaCodecLinearBlock.h
+++ b/media/jni/android_media_MediaCodecLinearBlock.h
@@ -44,12 +44,19 @@
std::shared_ptr<C2Buffer> toC2Buffer(size_t offset, size_t size) const {
if (mBuffer) {
+ // TODO: if returned C2Buffer is different from mBuffer, we should
+ // find a way to connect the life cycle between this C2Buffer and
+ // mBuffer.
if (mBuffer->data().type() != C2BufferData::LINEAR) {
return nullptr;
}
C2ConstLinearBlock block = mBuffer->data().linearBlocks().front();
if (offset == 0 && size == block.capacity()) {
- return mBuffer;
+ // Let C2Buffer be new one to queue to MediaCodec. It will allow
+ // the related input slot to be released by onWorkDone from C2
+ // Component. Currently, the life cycle of mBuffer should be
+ // protected by different flows.
+ return std::make_shared<C2Buffer>(*mBuffer);
}
std::shared_ptr<C2Buffer> buffer =
diff --git a/mime/java/Android.bp b/mime/java/Android.bp
index 07cada8e..a267d65 100644
--- a/mime/java/Android.bp
+++ b/mime/java/Android.bp
@@ -10,5 +10,8 @@
filegroup {
name: "framework-mime-sources",
srcs: ["**/*.java"],
- visibility: ["//frameworks/base"],
+ visibility: [
+ "//frameworks/base",
+ "//frameworks/base/api",
+ ],
}
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
index 9e0a6eb..294ca9c 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -86,7 +86,7 @@
return nullptr;
}
- String16 fileName(obbFile->getFileName());
+ String16 fileName(canonicalPath);
String16 packageName(obbFile->getPackageName());
size_t length;
const unsigned char* salt = obbFile->getSalt(&length);
diff --git a/native/android/tests/activitymanager/nativeTests/Android.bp b/native/android/tests/activitymanager/nativeTests/Android.bp
index 528ac12..ebd7533 100644
--- a/native/android/tests/activitymanager/nativeTests/Android.bp
+++ b/native/android/tests/activitymanager/nativeTests/Android.bp
@@ -45,4 +45,7 @@
required: [
"UidImportanceHelperApp",
],
+ data: [
+ ":UidImportanceHelperApp",
+ ],
}
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index 1765348..cd40438 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -39,6 +39,10 @@
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
+ <intent-filter>
+ <action android:name="android.os.image.action.START_INSTALL" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
</activity>
<receiver
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 5562684..5e42f70 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -19,6 +19,7 @@
import static android.os.AsyncTask.Status.FINISHED;
import static android.os.AsyncTask.Status.PENDING;
import static android.os.AsyncTask.Status.RUNNING;
+import static android.os.image.DynamicSystemClient.ACTION_HIDE_NOTIFICATION;
import static android.os.image.DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE;
import static android.os.image.DynamicSystemClient.ACTION_START_INSTALL;
import static android.os.image.DynamicSystemClient.CAUSE_ERROR_EXCEPTION;
@@ -27,6 +28,8 @@
import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_CANCELLED;
import static android.os.image.DynamicSystemClient.CAUSE_INSTALL_COMPLETED;
import static android.os.image.DynamicSystemClient.CAUSE_NOT_SPECIFIED;
+import static android.os.image.DynamicSystemClient.KEY_ENABLE_WHEN_COMPLETED;
+import static android.os.image.DynamicSystemClient.KEY_ONE_SHOT;
import static android.os.image.DynamicSystemClient.STATUS_IN_PROGRESS;
import static android.os.image.DynamicSystemClient.STATUS_IN_USE;
import static android.os.image.DynamicSystemClient.STATUS_NOT_STARTED;
@@ -77,8 +80,6 @@
private static final String TAG = "DynamicSystemInstallationService";
- // TODO (b/131866826): This is currently for test only. Will move this to System API.
- static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED";
static final String KEY_DSU_SLOT = "KEY_DSU_SLOT";
static final String DEFAULT_DSU_SLOT = "dsu";
static final String KEY_PUBKEY = "KEY_PUBKEY";
@@ -172,6 +173,8 @@
// This is for testing only now
private boolean mEnableWhenCompleted;
+ private boolean mOneShot;
+ private boolean mHideNotification;
private InstallationAsyncTask.Progress mInstallTaskProgress;
private InstallationAsyncTask mInstallTask;
@@ -229,6 +232,8 @@
executeRebootToNormalCommand();
} else if (ACTION_NOTIFY_IF_IN_USE.equals(action)) {
executeNotifyIfInUseCommand();
+ } else if (ACTION_HIDE_NOTIFICATION.equals(action)) {
+ executeHideNotificationCommand();
}
return Service.START_NOT_STICKY;
@@ -318,6 +323,7 @@
long systemSize = intent.getLongExtra(DynamicSystemClient.KEY_SYSTEM_SIZE, 0);
long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0);
mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false);
+ mOneShot = intent.getBooleanExtra(KEY_ONE_SHOT, true);
String dsuSlot = intent.getStringExtra(KEY_DSU_SLOT);
String publicKey = intent.getStringExtra(KEY_PUBKEY);
@@ -384,9 +390,9 @@
boolean enabled = false;
if (mInstallTask != null && mInstallTask.isCompleted()) {
- enabled = mInstallTask.commit();
+ enabled = mInstallTask.commit(mOneShot);
} else if (isDynamicSystemInstalled()) {
- enabled = mDynSystem.setEnable(true, true);
+ enabled = mDynSystem.setEnable(true, mOneShot);
} else {
Log.e(TAG, "Trying to reboot to AOT while there is no complete installation");
return;
@@ -439,12 +445,16 @@
private void executeNotifyIfInUseCommand() {
switch (getStatus()) {
case STATUS_IN_USE:
- startForeground(NOTIFICATION_ID,
- buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED));
+ if (!mHideNotification) {
+ startForeground(NOTIFICATION_ID,
+ buildNotification(STATUS_IN_USE, CAUSE_NOT_SPECIFIED));
+ }
break;
case STATUS_READY:
- startForeground(NOTIFICATION_ID,
- buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED));
+ if (!mHideNotification) {
+ startForeground(NOTIFICATION_ID,
+ buildNotification(STATUS_READY, CAUSE_NOT_SPECIFIED));
+ }
break;
case STATUS_IN_PROGRESS:
break;
@@ -454,6 +464,16 @@
}
}
+ private void executeHideNotificationCommand() {
+ mHideNotification = true;
+ switch (getStatus()) {
+ case STATUS_IN_USE:
+ case STATUS_READY:
+ stopForeground(STOP_FOREGROUND_REMOVE);
+ break;
+ }
+ }
+
private void resetTaskAndStop() {
resetTaskAndStop(/* removeNotification= */ false);
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index a41399f..42b620a 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -803,7 +803,7 @@
return mIsCompleted;
}
- boolean commit() {
- return mDynSystem.setEnable(true, true);
+ boolean commit(boolean oneShot) {
+ return mDynSystem.setEnable(true, oneShot);
}
}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
index 64e42cc..b522729 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/VerificationActivity.java
@@ -16,6 +16,8 @@
package com.android.dynsystem;
+import static android.os.image.DynamicSystemClient.KEY_KEYGUARD_USE_DEFAULT_STRINGS;
+
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Context;
@@ -47,10 +49,7 @@
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
if (km != null) {
- String title = getString(R.string.keyguard_title);
- String description = getString(R.string.keyguard_description);
- Intent intent = km.createConfirmDeviceCredentialIntent(title, description);
-
+ Intent intent = createConfirmDeviceCredentialIntent(km);
if (intent == null) {
Log.d(TAG, "This device is not protected by a password/pin");
startInstallationService();
@@ -63,6 +62,23 @@
}
}
+ private Intent createConfirmDeviceCredentialIntent(KeyguardManager km) {
+ final boolean useDefaultStrings =
+ getIntent().getBooleanExtra(KEY_KEYGUARD_USE_DEFAULT_STRINGS, false);
+ final String title;
+ final String description;
+ if (useDefaultStrings) {
+ // Use default strings provided by keyguard manager
+ title = null;
+ description = null;
+ } else {
+ // Use custom strings provided by DSU
+ title = getString(R.string.keyguard_title);
+ description = getString(R.string.keyguard_description);
+ }
+ return km.createConfirmDeviceCredentialIntent(title, description);
+ }
+
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
diff --git a/packages/PrintSpooler/tests/outofprocess/Android.bp b/packages/PrintSpooler/tests/outofprocess/Android.bp
index 69a1d7f..ef0d122 100644
--- a/packages/PrintSpooler/tests/outofprocess/Android.bp
+++ b/packages/PrintSpooler/tests/outofprocess/Android.bp
@@ -31,7 +31,7 @@
libs: ["android.test.runner.stubs"],
static_libs: [
"androidx.test.rules",
- "ub-uiautomator",
+ "androidx.test.uiautomator_uiautomator",
"mockito-target-minus-junit4",
"print-test-util-lib",
],
diff --git a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
index 132545b..1509b70 100644
--- a/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
+++ b/packages/PrintSpooler/tests/outofprocess/src/com/android/printspooler/outofprocess/tests/WorkflowTest.java
@@ -35,15 +35,15 @@
import android.print.test.services.FirstPrintService;
import android.print.test.services.PrinterDiscoverySessionCallbacks;
import android.print.test.services.StubbablePrinterDiscoverySession;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
import android.util.Log;
import androidx.test.filters.LargeTest;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
index f305fd3..e92157e 100644
--- a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
+++ b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
@@ -47,7 +47,7 @@
* Annotation processor for {@link SearchIndexable} that generates {@link SearchIndexableResources}
* subclasses.
*/
-@SupportedSourceVersion(SourceVersion.RELEASE_11)
+@SupportedSourceVersion(SourceVersion.RELEASE_17)
@SupportedAnnotationTypes({"com.android.settingslib.search.SearchIndexable"})
public class IndexableProcessor extends AbstractProcessor {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 879181f..2d958a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -6,6 +6,7 @@
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothCsipSetCoordinator;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
@@ -162,14 +163,21 @@
resources, ((BitmapDrawable) pair.first).getBitmap()), pair.second);
}
+ int hashCode;
+ if ((cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID)) {
+ hashCode = new Integer(cachedDevice.getGroupId()).hashCode();
+ } else {
+ hashCode = cachedDevice.getAddress().hashCode();
+ }
+
return new Pair<>(buildBtRainbowDrawable(context,
- pair.first, cachedDevice.getAddress().hashCode()), pair.second);
+ pair.first, hashCode), pair.second);
}
/**
* Build Bluetooth device icon with rainbow
*/
- public static Drawable buildBtRainbowDrawable(Context context, Drawable drawable,
+ private static Drawable buildBtRainbowDrawable(Context context, Drawable drawable,
int hashCode) {
final Resources resources = context.getResources();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index fe448fc..6ef5d73 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -576,9 +576,14 @@
*/
public void setName(String name) {
// Prevent getName() to be set to null if setName(null) is called
- if (name != null && !TextUtils.equals(name, getName())) {
- mDevice.setAlias(name);
- dispatchAttributesChanged();
+ if (name == null || TextUtils.equals(name, getName())) {
+ return;
+ }
+ mDevice.setAlias(name);
+ dispatchAttributesChanged();
+
+ for (CachedBluetoothDevice cbd : mMemberDevices) {
+ cbd.setName(name);
}
}
@@ -1497,8 +1502,7 @@
refresh();
}
- return new Pair<>(BluetoothUtils.buildBtRainbowDrawable(
- mContext, pair.first, getAddress().hashCode()), pair.second);
+ return BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, this);
}
void releaseLruCache() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
index fb3f382..e91d697 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXml.java
@@ -324,6 +324,7 @@
if (!TextUtils.isEmpty(noticeHeader)) {
writer.println(noticeHeader);
+ writer.println("<br/>");
}
int count = 0;
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
index 39b4b8e..35e3dd3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java
@@ -231,7 +231,7 @@
public SignalStrength signalStrength;
public TelephonyDisplayInfo telephonyDisplayInfo =
new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false);
/**
* Empty constructor
diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS
index 0f88811..d901e2c 100644
--- a/packages/SettingsProvider/src/android/provider/settings/OWNERS
+++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS
@@ -1,4 +1,4 @@
# Bug component: 656484
-include platform/frameworks/base:/services/backup/OWNERS
+include platform/frameworks/base:/services/backup/BACKUP_OWNERS
diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS
index 0f88811..db4b27c 100644
--- a/packages/SettingsProvider/test/src/android/provider/OWNERS
+++ b/packages/SettingsProvider/test/src/android/provider/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 656484
-include platform/frameworks/base:/services/backup/OWNERS
-
+include platform/frameworks/base:/services/backup/BACKUP_OWNERS
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index 402d73c..811b409 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -55,6 +55,7 @@
madym@google.com
mankoff@google.com
mateuszc@google.com
+mgalhardo@google.com
michaelmikhil@google.com
michschn@google.com
mkephart@google.com
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 0f81b0b..3889030 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -298,10 +298,16 @@
) {
val view =
openedDialogs.firstOrNull { it.dialog == animateFrom }?.dialogContentWithBackground
- ?: throw IllegalStateException(
- "The animateFrom dialog was not animated using " +
- "DialogLaunchAnimator.showFrom(View|Dialog)"
- )
+ if (view == null) {
+ Log.w(
+ TAG,
+ "Showing dialog $dialog normally as the dialog it is shown from was not shown " +
+ "using DialogLaunchAnimator"
+ )
+ dialog.show()
+ return
+ }
+
showFromView(
dialog,
view,
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 3b71dc3..d10332b 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -78,7 +78,7 @@
android:layout_width="match_parent"
android:clipChildren="false">
<ViewStub
- android:id="@+id/operator_name"
+ android:id="@+id/operator_name_stub"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout="@layout/operator_name" />
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
index a16f3047..8658c64 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java
@@ -52,7 +52,7 @@
private ProgressDialog mSimUnlockProgressDialog;
private CheckSimPin mCheckSimPinThread;
- private int mRemainingAttempts;
+ private int mRemainingAttempts = -1;
// Below flag is set to true during power-up or when a new SIM card inserted on device.
// When this is true and when SIM card is PIN locked state, on PIN lock screen, message would
// be displayed to inform user about the number of remaining PIN attempts left.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 93027c1..92054b3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1840,6 +1840,8 @@
state = TelephonyManager.SIM_STATE_PIN_REQUIRED;
} else if (Intent.SIM_LOCKED_ON_PUK.equals(lockedReason)) {
state = TelephonyManager.SIM_STATE_PUK_REQUIRED;
+ } else if (Intent.SIM_ABSENT_ON_PERM_DISABLED.equals(lockedReason)) {
+ state = TelephonyManager.SIM_STATE_PERM_DISABLED;
} else {
state = TelephonyManager.SIM_STATE_UNKNOWN;
}
@@ -2735,7 +2737,8 @@
boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
&& shouldListenBouncerState && shouldListenUdfpsState
- && shouldListenSideFpsState;
+ && shouldListenSideFpsState
+ && !isFingerprintLockedOut();
logListenerModelData(
new KeyguardFingerprintListenModel(
System.currentTimeMillis(),
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index 03d999f..9f948a7 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -325,7 +325,9 @@
// TODO(b/140051051)
final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
.getIntForUser(getContext().getContentResolver(),
- SHOW_BATTERY_PERCENT, 0, UserHandle.USER_CURRENT));
+ SHOW_BATTERY_PERCENT, getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_defaultBatteryPercentageSetting)
+ ? 1 : 0, UserHandle.USER_CURRENT));
boolean shouldShow =
(mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
|| mShowPercentMode == MODE_ON
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 2e6ea0e..54946ee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -144,7 +144,7 @@
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final TelephonyDisplayInfo DEFAULT_TELEPHONY_DISPLAY_INFO =
new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false);
static final int MAX_WIFI_ENTRY_COUNT = 3;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
index 1fb6a98..c37b01f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
@@ -49,7 +49,7 @@
) : ConnectivityState() {
@JvmField var telephonyDisplayInfo = TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE)
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false)
@JvmField var serviceState: ServiceState? = null
@JvmField var signalStrength: SignalStrength? = null
@@ -131,7 +131,7 @@
}
fun isRoaming(): Boolean {
- return serviceState != null && serviceState!!.roaming
+ return telephonyDisplayInfo != null && telephonyDisplayInfo.isRoaming
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 9f3fd72..5ca7ba0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -636,9 +636,9 @@
private void initOperatorName() {
int subId = SubscriptionManager.getDefaultDataSubscriptionId();
if (mCarrierConfigTracker.getShowOperatorNameInStatusBarConfig(subId)) {
- ViewStub stub = mStatusBar.findViewById(R.id.operator_name);
+ View view = mStatusBar.findViewById(R.id.operator_name);
mOperatorNameViewController =
- mOperatorNameViewControllerFactory.create((OperatorNameView) stub.inflate());
+ mOperatorNameViewControllerFactory.create((OperatorNameView) view);
mOperatorNameViewController.init();
// This view should not be visible on lock-screen
if (mKeyguardStateController.isShowing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
index 730ecde..8f9f019 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone.fragment.dagger;
import android.view.View;
+import android.view.ViewStub;
import com.android.systemui.R;
import com.android.systemui.battery.BatteryMeterView;
@@ -95,7 +96,7 @@
@StatusBarFragmentScope
@Named(OPERATOR_NAME_VIEW)
static View provideOperatorNameView(@RootView PhoneStatusBarView view) {
- return view.findViewById(R.id.operator_name);
+ return ((ViewStub) view.findViewById(R.id.operator_name_stub)).inflate();
}
/** */
diff --git a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
index 05e5666..29f16c7 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
@@ -272,10 +272,10 @@
private static boolean showApplicationIcon(ApplicationInfo appInfo,
PackageManager packageManager) {
- if (hasFlag(appInfo.flags, FLAG_UPDATED_SYSTEM_APP)) {
+ if (hasFlag(appInfo.flags, FLAG_UPDATED_SYSTEM_APP | FLAG_SYSTEM)) {
return packageManager.getLaunchIntentForPackage(appInfo.packageName) != null;
}
- return !hasFlag(appInfo.flags, FLAG_SYSTEM);
+ return true;
}
private static boolean hasFlag(int flags, int flag) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 13cd328..73e11d7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -28,6 +28,7 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
+import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
@@ -1040,10 +1041,11 @@
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
- // Fingerprint should be restarted once its cancelled bc on lockout, the device
- // can still detectFingerprint (and if it's not locked out, fingerprint can listen)
+ // Fingerprint should be cancelled on lockout if going to lockout state, else
+ // restarted if it's not
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
- .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
+ .isEqualTo(fpLocked
+ ? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
index cac4a0e..82af0f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
@@ -260,6 +260,12 @@
assertThat(touchSurface.visibility).isEqualTo(View.GONE)
}
+ @Test
+ fun showFromDialogDoesNotCrashWhenShownFromRandomDialog() {
+ val dialog = createDialogAndShowFromDialog(animateFrom = TestDialog(context))
+ dialog.dismiss()
+ }
+
private fun createAndShowDialog(
animator: DialogLaunchAnimator = dialogLaunchAnimator,
): TestDialog {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1e9c3b7..c7a7959 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1842,6 +1842,12 @@
AccessibilityServiceInfo accessibilityServiceInfo;
try {
accessibilityServiceInfo = new AccessibilityServiceInfo(resolveInfo, mContext);
+ if (!accessibilityServiceInfo.isWithinParcelableSize()) {
+ Slog.e(LOG_TAG, "Skipping service "
+ + accessibilityServiceInfo.getResolveInfo().getComponentInfo()
+ + " because service info size is larger than safe parcelable limits.");
+ continue;
+ }
if (userState.mCrashedServices.contains(serviceInfo.getComponentName())) {
// Restore the crashed attribute.
accessibilityServiceInfo.crashed = true;
diff --git a/services/backup/BACKUP_OWNERS b/services/backup/BACKUP_OWNERS
new file mode 100644
index 0000000..f8f4f4f
--- /dev/null
+++ b/services/backup/BACKUP_OWNERS
@@ -0,0 +1,10 @@
+# Bug component: 1193469
+
+jstemmer@google.com
+martinoh@google.com
+millmore@google.com
+niamhfw@google.com
+piee@google.com
+philippov@google.com
+rthakohov@google.com
+sarpm@google.com
\ No newline at end of file
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 79709a3..3bd2db1 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -2,12 +2,4 @@
set noparent
-bryanmawhinney@google.com
-jstemmer@google.com
-martinoh@google.com
-millmore@google.com
-niamhfw@google.com
-piee@google.com
-philippov@google.com
-rthakohov@google.com
-sarpm@google.com
+include platform/frameworks/base:/services/backup/BACKUP_OWNERS
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 6a14dea..d885cd1 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -155,6 +155,7 @@
"android.hardware.health-V2-java", // AIDL
"android.hardware.health-translate-java",
"android.hardware.light-V1-java",
+ "android.hardware.security.rkp-V3-java",
"android.hardware.tv.cec-V1.1-java",
"android.hardware.tv.hdmi.cec-V1-java",
"android.hardware.tv.hdmi.connection-V1-java",
@@ -171,6 +172,7 @@
"android.hardware.power-V3-java",
"android.hidl.manager-V1.2-java",
"capture_state_listener-aidl-java",
+ "cbor-java",
"icu4j_calendar_astronomer",
"netd-client",
"overlayable_policy_aidl-java",
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 27215b2..b0c1d05 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -44,7 +44,7 @@
private static final String TAG = "DynamicSystemService";
private static final long MINIMUM_SD_MB = (30L << 10);
private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
- private static final String PATH_DEFAULT = "/data/gsi/";
+ private static final String PATH_DEFAULT = "/data/gsi/dsu/";
private Context mContext;
private String mInstallPath, mDsuSlot;
private volatile IGsiService mGsiService;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 2aa9378..17cdfdb2 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -56,7 +56,6 @@
import android.net.NetworkStack;
import android.net.NetworkStats;
import android.net.RouteInfo;
-import android.net.UidRangeParcel;
import android.net.util.NetdService;
import android.os.BatteryStats;
import android.os.Binder;
@@ -97,7 +96,6 @@
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -1346,70 +1344,6 @@
}
}
- private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
- // UID ranges to close sockets on.
- UidRangeParcel[] ranges;
- // UID ranges whose sockets we won't touch.
- int[] exemptUids;
-
- int numUids = 0;
- if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
- if (getFirewallType(chain) == FIREWALL_ALLOWLIST) {
- // Close all sockets on all non-system UIDs...
- ranges = new UidRangeParcel[] {
- // TODO: is there a better way of finding all existing users? If so, we could
- // specify their ranges here.
- new UidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
- };
- // ... except for the UIDs that have allow rules.
- synchronized (mRulesLock) {
- final SparseIntArray rules = getUidFirewallRulesLR(chain);
- exemptUids = new int[rules.size()];
- for (int i = 0; i < exemptUids.length; i++) {
- if (rules.valueAt(i) == FIREWALL_RULE_ALLOW) {
- exemptUids[numUids] = rules.keyAt(i);
- numUids++;
- }
- }
- }
- // Normally, allowlist chains only contain deny rules, so numUids == exemptUids.length.
- // But the code does not guarantee this in any way, and at least in one case - if we add
- // a UID rule to the firewall, and then disable the firewall - the chains can contain
- // the wrong type of rule. In this case, don't close connections that we shouldn't.
- //
- // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
- // fix setFirewallEnabled to grab mQuotaLock and clear rules.
- if (numUids != exemptUids.length) {
- exemptUids = Arrays.copyOf(exemptUids, numUids);
- }
- } else {
- // Close sockets for every UID that has a deny rule...
- synchronized (mRulesLock) {
- final SparseIntArray rules = getUidFirewallRulesLR(chain);
- ranges = new UidRangeParcel[rules.size()];
- for (int i = 0; i < ranges.length; i++) {
- if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
- int uid = rules.keyAt(i);
- ranges[numUids] = new UidRangeParcel(uid, uid);
- numUids++;
- }
- }
- }
- // As above; usually numUids == ranges.length, but not always.
- if (numUids != ranges.length) {
- ranges = Arrays.copyOf(ranges, numUids);
- }
- // ... with no exceptions.
- exemptUids = new int[0];
- }
-
- try {
- mNetdService.socketDestroy(ranges, exemptUids);
- } catch(RemoteException | ServiceSpecificException e) {
- Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
- }
- }
-
@Override
public void setFirewallChainEnabled(int chain, boolean enable) {
enforceSystemUid();
@@ -1434,14 +1368,6 @@
} catch (RuntimeException e) {
throw new IllegalStateException(e);
}
-
- // Close any sockets that were opened by the affected UIDs. This has to be done after
- // disabling network connectivity, in case they react to the socket close by reopening
- // the connection and race with the iptables commands that enable the firewall. All
- // allowlist and denylist chains allow RSTs through.
- if (enable) {
- closeSocketsForFirewallChainLocked(chain, chainName);
- }
}
}
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 409f054..123cd328 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -27,6 +27,7 @@
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 *SoundTrigger* = file:/media/java/android/media/soundtrigger/OWNERS
per-file *Storage* = file:/core/java/android/os/storage/OWNERS
per-file *TimeUpdate* = file:/services/core/java/com/android/server/timezonedetector/OWNERS
per-file DynamicSystemService.java = file:/packages/DynamicSystemInstallationService/OWNERS
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index ce9c067..2daf04d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -75,6 +75,9 @@
import android.content.pm.UserInfo;
import android.content.res.ObbInfo;
import android.database.ContentObserver;
+import android.media.MediaCodecList;
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
@@ -1006,10 +1009,27 @@
}
}
+ private boolean isHevcDecoderSupported() {
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
+ for (MediaCodecInfo codecInfo : codecInfos) {
+ if (codecInfo.isEncoder()) {
+ continue;
+ }
+ String[] supportedTypes = codecInfo.getSupportedTypes();
+ for (String type : supportedTypes) {
+ if (type.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private void configureTranscoding() {
// See MediaProvider TranscodeHelper#getBooleanProperty for more information
boolean transcodeEnabled = false;
- boolean defaultValue = true;
+ boolean defaultValue = isHevcDecoderSupported() ? true : false;
if (SystemProperties.getBoolean("persist.sys.fuse.transcode_user_control", false)) {
transcodeEnabled = SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled",
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index a69d3f0..1afda65 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1578,57 +1578,62 @@
return;
}
- synchronized (mRecords) {
- String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId
- + " state=" + state;
- if (VDBG) {
- log(str);
- }
- mLocalLog.log(str);
- // for service state updates, don't notify clients when subId is invalid. This prevents
- // us from sending incorrect notifications like b/133140128
- // In the future, we can remove this logic for every notification here and add a
- // callback so listeners know when their PhoneStateListener's subId becomes invalid, but
- // for now we use the simplest fix.
- if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) {
- mServiceState[phoneId] = state;
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mRecords) {
+ String str = "notifyServiceStateForSubscriber: subId=" + subId + " phoneId="
+ + phoneId + " state=" + state;
+ if (VDBG) {
+ log(str);
+ }
+ mLocalLog.log(str);
+ // for service state updates, don't notify clients when subId is invalid. This
+ // prevents us from sending incorrect notifications like b/133140128
+ // In the future, we can remove this logic for every notification here and add a
+ // callback so listeners know when their PhoneStateListener's subId becomes invalid,
+ // but for now we use the simplest fix.
+ if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) {
+ mServiceState[phoneId] = state;
- for (Record r : mRecords) {
- if (VDBG) {
- log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
- + " phoneId=" + phoneId + " state=" + state);
- }
- if (r.matchTelephonyCallbackEvent(
- TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)
- && idMatch(r, subId, phoneId)) {
+ for (Record r : mRecords) {
+ if (VDBG) {
+ log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
+ + " phoneId=" + phoneId + " state=" + state);
+ }
+ if (r.matchTelephonyCallbackEvent(
+ TelephonyCallback.EVENT_SERVICE_STATE_CHANGED)
+ && idMatch(r, subId, phoneId)) {
- try {
- ServiceState stateToSend;
- if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = new ServiceState(state);
- } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
- stateToSend = state.createLocationInfoSanitizedCopy(false);
- } else {
- stateToSend = state.createLocationInfoSanitizedCopy(true);
+ try {
+ ServiceState stateToSend;
+ if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+ stateToSend = new ServiceState(state);
+ } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+ stateToSend = state.createLocationInfoSanitizedCopy(false);
+ } else {
+ stateToSend = state.createLocationInfoSanitizedCopy(true);
+ }
+ if (DBG) {
+ log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
+ + " subId=" + subId + " phoneId=" + phoneId
+ + " state=" + stateToSend);
+ }
+ r.callback.onServiceStateChanged(stateToSend);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
}
- if (DBG) {
- log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
- + " subId=" + subId + " phoneId=" + phoneId
- + " state=" + state);
- }
- r.callback.onServiceStateChanged(stateToSend);
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
}
}
+ } else {
+ log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId
+ + " or subId=" + subId);
}
- } else {
- log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId
- + " or subId=" + subId);
+ handleRemoveListLocked();
}
- handleRemoveListLocked();
+ broadcastServiceStateChanged(state, phoneId, subId);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
}
- broadcastServiceStateChanged(state, phoneId, subId);
}
public void notifySimActivationStateChangedForPhoneId(int phoneId, int subId,
@@ -1957,7 +1962,8 @@
&& overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED) {
overrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE;
}
- return new TelephonyDisplayInfo(networkType, overrideNetworkType);
+ boolean isRoaming = telephonyDisplayInfo.isRoaming();
+ return new TelephonyDisplayInfo(networkType, overrideNetworkType, isRoaming);
}
public void notifyCallForwardingChanged(boolean cfi) {
@@ -3160,13 +3166,10 @@
public static final String ACTION_SIGNAL_STRENGTH_CHANGED = "android.intent.action.SIG_STR";
private void broadcastServiceStateChanged(ServiceState state, int phoneId, int subId) {
- final long ident = Binder.clearCallingIdentity();
try {
mBatteryStats.notePhoneState(state.getState());
} catch (RemoteException re) {
// Can't do much
- } finally {
- Binder.restoreCallingIdentity(ident);
}
// Send the broadcast exactly once to all possible disjoint sets of apps.
@@ -3183,8 +3186,7 @@
// - Sanitized ServiceState sent to all other apps with READ_PHONE_STATE
// - Sanitized ServiceState sent to all other apps with READ_PRIVILEGED_PHONE_STATE but not
// READ_PHONE_STATE
- if (Binder.withCleanCallingIdentity(() ->
- LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId()))) {
+ if (LocationAccessPolicy.isLocationModeEnabled(mContext, mContext.getUserId())) {
Intent fullIntent = createServiceStateIntent(state, subId, phoneId, false);
mContext.createContextAsUser(UserHandle.ALL, 0).sendBroadcastMultiplePermissions(
fullIntent,
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index f652cb0..e8c85ce 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -1074,9 +1074,10 @@
subGrp, mLastSnapshot, mConfigs.get(subGrp));
for (int restrictedTransport : restrictedTransports) {
if (ncCopy.hasTransport(restrictedTransport)) {
- if (restrictedTransport == TRANSPORT_CELLULAR) {
- // Only make a cell network as restricted when the VCN is in
- // active mode.
+ if (restrictedTransport == TRANSPORT_CELLULAR
+ || restrictedTransport == TRANSPORT_TEST) {
+ // For cell or test network, only mark it as restricted when
+ // the VCN is in active mode.
isRestricted |= (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE);
} else {
isRestricted = true;
@@ -1104,7 +1105,7 @@
final NetworkCapabilities result = ncBuilder.build();
final VcnUnderlyingNetworkPolicy policy = new VcnUnderlyingNetworkPolicy(
mTrackingNetworkCallback
- .requiresRestartForImmutableCapabilityChanges(result),
+ .requiresRestartForImmutableCapabilityChanges(result, linkProperties),
result);
logVdbg("getUnderlyingNetworkPolicy() called for caps: " + networkCapabilities
@@ -1354,19 +1355,29 @@
* without requiring a Network restart.
*/
private class TrackingNetworkCallback extends ConnectivityManager.NetworkCallback {
+ private final Object mLockObject = new Object();
private final Map<Network, NetworkCapabilities> mCaps = new ArrayMap<>();
+ private final Map<Network, LinkProperties> mLinkProperties = new ArrayMap<>();
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities caps) {
- synchronized (mCaps) {
+ synchronized (mLockObject) {
mCaps.put(network, caps);
}
}
@Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
+ synchronized (mLockObject) {
+ mLinkProperties.put(network, lp);
+ }
+ }
+
+ @Override
public void onLost(Network network) {
- synchronized (mCaps) {
+ synchronized (mLockObject) {
mCaps.remove(network);
+ mLinkProperties.remove(network);
}
}
@@ -1393,22 +1404,28 @@
return true;
}
- private boolean requiresRestartForImmutableCapabilityChanges(NetworkCapabilities caps) {
+ private boolean requiresRestartForImmutableCapabilityChanges(
+ NetworkCapabilities caps, LinkProperties lp) {
if (caps.getSubscriptionIds() == null) {
return false;
}
- synchronized (mCaps) {
- for (NetworkCapabilities existing : mCaps.values()) {
- if (caps.getSubscriptionIds().equals(existing.getSubscriptionIds())
- && hasSameTransportsAndCapabilities(caps, existing)) {
- // Restart if any immutable capabilities have changed
- return existing.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ synchronized (mLockObject) {
+ // Search for an existing network (using interfce names)
+ // TODO: Get network from NetworkFactory (if exists) for this match.
+ for (Entry<Network, LinkProperties> lpEntry : mLinkProperties.entrySet()) {
+ if (lp.getInterfaceName() != null
+ && !lp.getInterfaceName().isEmpty()
+ && Objects.equals(
+ lp.getInterfaceName(), lpEntry.getValue().getInterfaceName())) {
+ return mCaps.get(lpEntry.getKey())
+ .hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
!= caps.hasCapability(NET_CAPABILITY_NOT_RESTRICTED);
}
}
}
+ // If no network found, by definition does not need restart.
return false;
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 89447b4..f846741 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3091,7 +3091,7 @@
}
}
- Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
+ Intent intent = result.getParcelable(AccountManager.KEY_INTENT, Intent.class);
if (intent != null && notifyOnAuthFailure && !customTokens) {
/*
* Make sure that the supplied intent is owned by the authenticator
@@ -3516,8 +3516,7 @@
Bundle.setDefusable(result, true);
mNumResults++;
Intent intent = null;
- if (result != null
- && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
+ if (result != null) {
if (!checkKeyIntent(
Binder.getCallingUid(),
result)) {
@@ -4886,8 +4885,10 @@
EventLog.writeEvent(0x534e4554, "250588548", authUid, "");
return false;
}
-
Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class);
+ if (intent == null) {
+ return true;
+ }
// Explicitly set an empty ClipData to ensure that we don't offer to
// promote any Uris contained inside for granting purposes
if (intent.getClipData() == null) {
@@ -4937,8 +4938,12 @@
Bundle simulateBundle = p.readBundle();
p.recycle();
Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class);
- return (intent.filterEquals(simulateBundle.getParcelable(AccountManager.KEY_INTENT,
- Intent.class)));
+ Intent simulateIntent = simulateBundle.getParcelable(AccountManager.KEY_INTENT,
+ Intent.class);
+ if (intent == null) {
+ return (simulateIntent == null);
+ }
+ return intent.filterEquals(simulateIntent);
}
private boolean isExportedSystemActivity(ActivityInfo activityInfo) {
@@ -5087,8 +5092,7 @@
}
}
}
- if (result != null
- && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
+ if (result != null) {
if (!checkKeyIntent(
Binder.getCallingUid(),
result)) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 9669c06..c36e070 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3420,6 +3420,11 @@
throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ className + " is not an isolatedProcess");
}
+ if (!mAm.getPackageManagerInternal().isSameApp(callingPackage, callingUid,
+ userId)) {
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ + "calling package not owned by calling UID ");
+ }
// Run the service under the calling package's application.
ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
callingPackage, ActivityManagerService.STOCK_PM_FLAGS, userId);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d48723a..148688f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8415,13 +8415,16 @@
}
}
+ boolean recoverable = eventType.equals("native_recoverable_crash");
+
EventLogTags.writeAmCrash(Binder.getCallingPid(),
UserHandle.getUserId(Binder.getCallingUid()), processName,
r == null ? -1 : r.info.flags,
crashInfo.exceptionClassName,
crashInfo.exceptionMessage,
crashInfo.throwFileName,
- crashInfo.throwLineNumber);
+ crashInfo.throwLineNumber,
+ recoverable ? 1 : 0);
int processClassEnum = processName.equals("system_server") ? ServerProtoEnums.SYSTEM_SERVER
: (r != null) ? r.getProcessClassEnum()
@@ -8489,7 +8492,15 @@
eventType, r, processName, null, null, null, null, null, null, crashInfo,
new Float(loadingProgress), incrementalMetrics, null);
- mAppErrors.crashApplication(r, crashInfo);
+ // For GWP-ASan recoverable crashes, don't make the app crash (the whole point of
+ // 'recoverable' is that the app doesn't crash). Normally, for nonrecoreable native crashes,
+ // debuggerd will terminate the process, but there's a backup where ActivityManager will
+ // also kill it. Avoid that.
+ if (recoverable) {
+ mAppErrors.sendRecoverableCrashToAppExitInfo(r, crashInfo);
+ } else {
+ mAppErrors.crashApplication(r, crashInfo);
+ }
}
public void handleApplicationStrictModeViolation(
@@ -10773,6 +10784,13 @@
pw.println("\n\n** Cache info for pid " + pid + " [" + r.processName + "] **");
pw.flush();
try {
+ if (pid == Process.myPid()) {
+ // Directly dump to target fd for local dump to avoid hang.
+ try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(fd.getInt$())) {
+ thread.dumpCacheInfo(pfd, args);
+ }
+ continue;
+ }
TransferPipe tp = new TransferPipe();
try {
thread.dumpCacheInfo(tp.getWriteFd(), args);
@@ -13089,12 +13107,17 @@
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, String receiverId, IIntentReceiver receiver,
IntentFilter filter, String permission, int userId, int flags) {
+ enforceNotIsolatedCaller("registerReceiver");
+
// Allow Sandbox process to register only unexported receivers.
- if ((flags & Context.RECEIVER_NOT_EXPORTED) != 0) {
- enforceNotIsolatedCaller("registerReceiver");
- } else if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()) {
- enforceNotIsolatedOrSdkSandboxCaller("registerReceiver");
+ boolean unexported = (flags & Context.RECEIVER_NOT_EXPORTED) != 0;
+ if (mSdkSandboxSettings.isBroadcastReceiverRestrictionsEnforced()
+ && Process.isSdkSandboxUid(Binder.getCallingUid())
+ && !unexported) {
+ throw new SecurityException("SDK sandbox process not allowed to call "
+ + "registerReceiver");
}
+
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
@@ -14657,6 +14680,17 @@
throw new SecurityException(msg);
}
}
+ if (!Build.IS_DEBUGGABLE && callingUid != ROOT_UID && callingUid != SHELL_UID
+ && callingUid != SYSTEM_UID && !hasActiveInstrumentationLocked(callingPid)) {
+ // If it's not debug build and not called from root/shell/system uid, reject it.
+ final String msg = "Permission Denial: instrumentation test "
+ + className + " from pid=" + callingPid + ", uid=" + callingUid
+ + ", pkgName=" + getPackageNameByPid(callingPid)
+ + " not allowed because it's not started from SHELL";
+ Slog.wtfQuiet(TAG, msg);
+ reportStartInstrumentationFailureLocked(watcher, className, msg);
+ throw new SecurityException(msg);
+ }
boolean disableHiddenApiChecks = ai.usesNonSdkApi()
|| (flags & INSTR_FLAG_DISABLE_HIDDEN_API_CHECKS) != 0;
@@ -14879,6 +14913,29 @@
}
}
+ @GuardedBy("this")
+ private boolean hasActiveInstrumentationLocked(int pid) {
+ if (pid == 0) {
+ return false;
+ }
+ synchronized (mPidsSelfLocked) {
+ ProcessRecord process = mPidsSelfLocked.get(pid);
+ return process != null && process.getActiveInstrumentation() != null;
+ }
+ }
+
+ private String getPackageNameByPid(int pid) {
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord app = mPidsSelfLocked.get(pid);
+
+ if (app != null && app.info != null) {
+ return app.info.packageName;
+ }
+
+ return null;
+ }
+ }
+
private boolean isCallerShell() {
final int callingUid = Binder.getCallingUid();
return callingUid == SHELL_UID || callingUid == ROOT_UID;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 08c1de6..c475f00 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -553,6 +553,15 @@
}
}
+ void sendRecoverableCrashToAppExitInfo(
+ ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
+ if (r == null || crashInfo == null
+ || !"Native crash".equals(crashInfo.exceptionClassName)) return;
+ synchronized (mService) {
+ mService.mProcessList.noteAppRecoverableCrash(r);
+ }
+ }
+
/**
* Bring up the "unexpected error" dialog box for a crashing app.
* Deal with edge cases (intercepts from instrumented applications,
diff --git a/services/core/java/com/android/server/am/AppExitInfoTracker.java b/services/core/java/com/android/server/am/AppExitInfoTracker.java
index 32d2071..df1f3c7 100644
--- a/services/core/java/com/android/server/am/AppExitInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppExitInfoTracker.java
@@ -308,6 +308,16 @@
mKillHandler.obtainMessage(KillHandler.MSG_APP_KILL, raw).sendToTarget();
}
+ void scheduleNoteAppRecoverableCrash(final ProcessRecord app) {
+ if (!mAppExitInfoLoaded.get() || app == null || app.info == null) return;
+
+ ApplicationExitInfo raw = obtainRawRecord(app, System.currentTimeMillis());
+ raw.setReason(ApplicationExitInfo.REASON_CRASH_NATIVE);
+ raw.setSubReason(ApplicationExitInfo.SUBREASON_UNKNOWN);
+ raw.setDescription("recoverable_crash");
+ mKillHandler.obtainMessage(KillHandler.MSG_APP_RECOVERABLE_CRASH, raw).sendToTarget();
+ }
+
void scheduleNoteAppKill(final int pid, final int uid, final @Reason int reason,
final @SubReason int subReason, final String msg) {
if (!mAppExitInfoLoaded.get()) {
@@ -421,8 +431,24 @@
scheduleLogToStatsdLocked(info, true);
}
+ /**
+ * Make note when ActivityManagerService gets a recoverable native crash, as the process isn't
+ * being killed but the crash should still be added to AppExitInfo. Also, because we're not
+ * crashing, don't log out to statsd.
+ */
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ void handleNoteAppRecoverableCrashLocked(final ApplicationExitInfo raw) {
+ addExitInfoLocked(raw, /* recoverable */ true);
+ }
+
@GuardedBy("mLock")
private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw) {
+ return addExitInfoLocked(raw, /* recoverable */ false);
+ }
+
+ @GuardedBy("mLock")
+ private ApplicationExitInfo addExitInfoLocked(ApplicationExitInfo raw, boolean recoverable) {
if (!mAppExitInfoLoaded.get()) {
Slog.w(TAG, "Skipping saving the exit info due to ongoing loading from storage");
return null;
@@ -438,7 +464,7 @@
}
}
for (int i = 0; i < packages.length; i++) {
- addExitInfoInnerLocked(packages[i], uid, info);
+ addExitInfoInnerLocked(packages[i], uid, info, recoverable);
}
schedulePersistProcessExitInfo(false);
@@ -845,7 +871,8 @@
}
@GuardedBy("mLock")
- private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info) {
+ private void addExitInfoInnerLocked(String packageName, int uid, ApplicationExitInfo info,
+ boolean recoverable) {
AppExitInfoContainer container = mData.get(packageName, uid);
if (container == null) {
container = new AppExitInfoContainer(mAppExitInfoHistoryListSize);
@@ -859,7 +886,11 @@
}
mData.put(packageName, uid, container);
}
- container.addExitInfoLocked(info);
+ if (recoverable) {
+ container.addRecoverableCrashLocked(info);
+ } else {
+ container.addExitInfoLocked(info);
+ }
}
@GuardedBy("mLock")
@@ -1284,38 +1315,40 @@
* A container class of {@link android.app.ApplicationExitInfo}
*/
final class AppExitInfoContainer {
- private SparseArray<ApplicationExitInfo> mInfos; // index is pid
+ private SparseArray<ApplicationExitInfo> mInfos; // index is a pid
+ private SparseArray<ApplicationExitInfo> mRecoverableCrashes; // index is a pid
private int mMaxCapacity;
private int mUid; // Application uid, not isolated uid.
AppExitInfoContainer(final int maxCapacity) {
mInfos = new SparseArray<ApplicationExitInfo>();
+ mRecoverableCrashes = new SparseArray<ApplicationExitInfo>();
mMaxCapacity = maxCapacity;
}
@GuardedBy("mLock")
- void getExitInfoLocked(final int filterPid, final int maxNum,
- ArrayList<ApplicationExitInfo> results) {
+ void getInfosLocked(SparseArray<ApplicationExitInfo> map, final int filterPid,
+ final int maxNum, ArrayList<ApplicationExitInfo> results) {
if (filterPid > 0) {
- ApplicationExitInfo r = mInfos.get(filterPid);
+ ApplicationExitInfo r = map.get(filterPid);
if (r != null) {
results.add(r);
}
} else {
- final int numRep = mInfos.size();
+ final int numRep = map.size();
if (maxNum <= 0 || numRep <= maxNum) {
// Return all records.
for (int i = 0; i < numRep; i++) {
- results.add(mInfos.valueAt(i));
+ results.add(map.valueAt(i));
}
Collections.sort(results,
(a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
} else {
if (maxNum == 1) {
// Most of the caller might be only interested with the most recent one
- ApplicationExitInfo r = mInfos.valueAt(0);
+ ApplicationExitInfo r = map.valueAt(0);
for (int i = 1; i < numRep; i++) {
- ApplicationExitInfo t = mInfos.valueAt(i);
+ ApplicationExitInfo t = map.valueAt(i);
if (r.getTimestamp() < t.getTimestamp()) {
r = t;
}
@@ -1326,7 +1359,7 @@
ArrayList<ApplicationExitInfo> list = mTmpInfoList2;
list.clear();
for (int i = 0; i < numRep; i++) {
- list.add(mInfos.valueAt(i));
+ list.add(map.valueAt(i));
}
Collections.sort(list,
(a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
@@ -1340,24 +1373,30 @@
}
@GuardedBy("mLock")
- void addExitInfoLocked(ApplicationExitInfo info) {
+ void getExitInfoLocked(final int filterPid, final int maxNum,
+ ArrayList<ApplicationExitInfo> results) {
+ getInfosLocked(mInfos, filterPid, maxNum, results);
+ }
+
+ @GuardedBy("mLock")
+ void addInfoLocked(SparseArray<ApplicationExitInfo> map, ApplicationExitInfo info) {
int size;
- if ((size = mInfos.size()) >= mMaxCapacity) {
+ if ((size = map.size()) >= mMaxCapacity) {
int oldestIndex = -1;
long oldestTimeStamp = Long.MAX_VALUE;
for (int i = 0; i < size; i++) {
- ApplicationExitInfo r = mInfos.valueAt(i);
+ ApplicationExitInfo r = map.valueAt(i);
if (r.getTimestamp() < oldestTimeStamp) {
oldestTimeStamp = r.getTimestamp();
oldestIndex = i;
}
}
if (oldestIndex >= 0) {
- final File traceFile = mInfos.valueAt(oldestIndex).getTraceFile();
+ final File traceFile = map.valueAt(oldestIndex).getTraceFile();
if (traceFile != null) {
traceFile.delete();
}
- mInfos.removeAt(oldestIndex);
+ map.removeAt(oldestIndex);
}
}
// Claim the state information if there is any
@@ -1367,7 +1406,17 @@
mActiveAppStateSummary, uid, pid));
info.setTraceFile(findAndRemoveFromSparse2dArray(mActiveAppTraces, uid, pid));
info.setAppTraceRetriever(mAppTraceRetriever);
- mInfos.append(pid, info);
+ map.append(pid, info);
+ }
+
+ @GuardedBy("mLock")
+ void addExitInfoLocked(ApplicationExitInfo info) {
+ addInfoLocked(mInfos, info);
+ }
+
+ @GuardedBy("mLock")
+ void addRecoverableCrashLocked(ApplicationExitInfo info) {
+ addInfoLocked(mRecoverableCrashes, info);
}
@GuardedBy("mLock")
@@ -1382,9 +1431,9 @@
}
@GuardedBy("mLock")
- void destroyLocked() {
- for (int i = mInfos.size() - 1; i >= 0; i--) {
- ApplicationExitInfo ai = mInfos.valueAt(i);
+ void destroyLocked(SparseArray<ApplicationExitInfo> map) {
+ for (int i = map.size() - 1; i >= 0; i--) {
+ ApplicationExitInfo ai = map.valueAt(i);
final File traceFile = ai.getTraceFile();
if (traceFile != null) {
traceFile.delete();
@@ -1395,24 +1444,37 @@
}
@GuardedBy("mLock")
+ void destroyLocked() {
+ destroyLocked(mInfos);
+ destroyLocked(mRecoverableCrashes);
+ }
+
+ @GuardedBy("mLock")
void forEachRecordLocked(final BiFunction<Integer, ApplicationExitInfo, Integer> callback) {
- if (callback != null) {
- for (int i = mInfos.size() - 1; i >= 0; i--) {
- switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) {
- case FOREACH_ACTION_REMOVE_ITEM:
- final File traceFile = mInfos.valueAt(i).getTraceFile();
- if (traceFile != null) {
- traceFile.delete();
- }
- mInfos.removeAt(i);
- break;
- case FOREACH_ACTION_STOP_ITERATION:
- i = 0;
- break;
- case FOREACH_ACTION_NONE:
- default:
- break;
- }
+ if (callback == null) return;
+ for (int i = mInfos.size() - 1; i >= 0; i--) {
+ switch (callback.apply(mInfos.keyAt(i), mInfos.valueAt(i))) {
+ case FOREACH_ACTION_STOP_ITERATION: return;
+ case FOREACH_ACTION_REMOVE_ITEM:
+ final File traceFile = mInfos.valueAt(i).getTraceFile();
+ if (traceFile != null) {
+ traceFile.delete();
+ }
+ mInfos.removeAt(i);
+ break;
+ }
+ }
+ for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
+ switch (callback.apply(
+ mRecoverableCrashes.keyAt(i), mRecoverableCrashes.valueAt(i))) {
+ case FOREACH_ACTION_STOP_ITERATION: return;
+ case FOREACH_ACTION_REMOVE_ITEM:
+ final File traceFile = mRecoverableCrashes.valueAt(i).getTraceFile();
+ if (traceFile != null) {
+ traceFile.delete();
+ }
+ mRecoverableCrashes.removeAt(i);
+ break;
}
}
}
@@ -1423,6 +1485,9 @@
for (int i = mInfos.size() - 1; i >= 0; i--) {
list.add(mInfos.valueAt(i));
}
+ for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
+ list.add(mRecoverableCrashes.valueAt(i));
+ }
Collections.sort(list, (a, b) -> Long.compare(b.getTimestamp(), a.getTimestamp()));
int size = list.size();
for (int i = 0; i < size; i++) {
@@ -1434,10 +1499,13 @@
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
proto.write(AppsExitInfoProto.Package.User.UID, mUid);
- int size = mInfos.size();
- for (int i = 0; i < size; i++) {
+ for (int i = 0; i < mInfos.size(); i++) {
mInfos.valueAt(i).writeToProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO);
}
+ for (int i = 0; i < mRecoverableCrashes.size(); i++) {
+ mRecoverableCrashes.valueAt(i).writeToProto(
+ proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH);
+ }
proto.end(token);
}
@@ -1448,14 +1516,23 @@
next != ProtoInputStream.NO_MORE_FIELDS;
next = proto.nextField()) {
switch (next) {
- case (int) AppsExitInfoProto.Package.User.UID:
+ case (int) AppsExitInfoProto.Package.User.UID: {
mUid = proto.readInt(AppsExitInfoProto.Package.User.UID);
break;
- case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO:
+ }
+ case (int) AppsExitInfoProto.Package.User.APP_EXIT_INFO: {
ApplicationExitInfo info = new ApplicationExitInfo();
info.readFromProto(proto, AppsExitInfoProto.Package.User.APP_EXIT_INFO);
mInfos.put(info.getPid(), info);
break;
+ }
+ case (int) AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH: {
+ ApplicationExitInfo info = new ApplicationExitInfo();
+ info.readFromProto(
+ proto, AppsExitInfoProto.Package.User.APP_RECOVERABLE_CRASH);
+ mRecoverableCrashes.put(info.getPid(), info);
+ break;
+ }
}
}
proto.end(token);
@@ -1472,6 +1549,11 @@
list.add(mInfos.valueAt(i));
}
}
+ for (int i = mRecoverableCrashes.size() - 1; i >= 0; i--) {
+ if (filterPid == 0 || filterPid == mRecoverableCrashes.keyAt(i)) {
+ list.add(mRecoverableCrashes.valueAt(i));
+ }
+ }
return list;
}
}
@@ -1610,6 +1692,7 @@
static final int MSG_PROC_DIED = 4103;
static final int MSG_APP_KILL = 4104;
static final int MSG_STATSD_LOG = 4105;
+ static final int MSG_APP_RECOVERABLE_CRASH = 4106;
KillHandler(Looper looper) {
super(looper, null, true);
@@ -1648,6 +1731,14 @@
}
}
break;
+ case MSG_APP_RECOVERABLE_CRASH: {
+ ApplicationExitInfo raw = (ApplicationExitInfo) msg.obj;
+ synchronized (mLock) {
+ handleNoteAppRecoverableCrashLocked(raw);
+ }
+ recycleRawRecord(raw);
+ }
+ break;
default:
super.handleMessage(msg);
}
diff --git a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
index ff78355..6268082 100644
--- a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
+++ b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
@@ -338,7 +338,7 @@
pw.print(prefix);
pw.print(mKeyNumOfEventsThreshold);
pw.print('=');
- pw.println(mDefaultNumOfEventsThreshold);
+ pw.println(mNumOfEventsThreshold);
}
pw.print(prefix);
pw.print("event_time_slot_size=");
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 702526a..1a0d291 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -399,7 +399,7 @@
}
}
- public void shutdown() {
+ public synchronized void shutdown() {
mExecutorService.shutdownNow();
}
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index d080036..6ce70a1 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -53,7 +53,7 @@
30037 am_process_start_timeout (User|1|5),(PID|1|5),(UID|1|5),(Process Name|3)
# Unhandled exception
-30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5)
+30039 am_crash (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Exception|3),(Message|3),(File|3),(Line|1|5),(Recoverable|1|5)
# Log.wtf() called
30040 am_wtf (User|1|5),(PID|1|5),(Process Name|3),(Flags|1|5),(Tag|3),(Message|3)
diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java
index 94eb076..cd119e7 100644
--- a/services/core/java/com/android/server/am/NativeCrashListener.java
+++ b/services/core/java/com/android/server/am/NativeCrashListener.java
@@ -64,12 +64,15 @@
class NativeCrashReporter extends Thread {
ProcessRecord mApp;
int mSignal;
+ boolean mGwpAsanRecoverableCrash;
String mCrashReport;
- NativeCrashReporter(ProcessRecord app, int signal, String report) {
+ NativeCrashReporter(ProcessRecord app, int signal, boolean gwpAsanRecoverableCrash,
+ String report) {
super("NativeCrashReport");
mApp = app;
mSignal = signal;
+ mGwpAsanRecoverableCrash = gwpAsanRecoverableCrash;
mCrashReport = report;
}
@@ -85,7 +88,9 @@
ci.stackTrace = mCrashReport;
if (DEBUG) Slog.v(TAG, "Calling handleApplicationCrash()");
- mAm.handleApplicationCrashInner("native_crash", mApp, mApp.processName, ci);
+ mAm.handleApplicationCrashInner(
+ mGwpAsanRecoverableCrash ? "native_recoverable_crash" : "native_crash",
+ mApp, mApp.processName, ci);
if (DEBUG) Slog.v(TAG, "<-- handleApplicationCrash() returned");
} catch (Exception e) {
Slog.e(TAG, "Unable to report native crash", e);
@@ -207,9 +212,14 @@
// permits crash_dump to connect to it. This allows us to trust the
// received values.
- // first, the pid and signal number
- int headerBytes = readExactly(fd, buf, 0, 8);
- if (headerBytes != 8) {
+ // Activity Manager protocol:
+ // - 32-bit network-byte-order: pid
+ // - 32-bit network-byte-order: signal number
+ // - byte: gwpAsanRecoverableCrash
+ // - bytes: raw text of the dump
+ // - null terminator
+ int headerBytes = readExactly(fd, buf, 0, 9);
+ if (headerBytes != 9) {
// protocol failure; give up
Slog.e(TAG, "Unable to read from debuggerd");
return;
@@ -217,69 +227,76 @@
int pid = unpackInt(buf, 0);
int signal = unpackInt(buf, 4);
+ boolean gwpAsanRecoverableCrash = buf[8] != 0;
if (DEBUG) {
- Slog.v(TAG, "Read pid=" + pid + " signal=" + signal);
+ Slog.v(TAG, "Read pid=" + pid + " signal=" + signal
+ + " recoverable=" + gwpAsanRecoverableCrash);
+ }
+ if (pid < 0) {
+ Slog.e(TAG, "Bogus pid!");
+ return;
}
// now the text of the dump
- if (pid > 0) {
- final ProcessRecord pr;
- synchronized (mAm.mPidsSelfLocked) {
- pr = mAm.mPidsSelfLocked.get(pid);
- }
- if (pr != null) {
- // Don't attempt crash reporting for persistent apps
- if (pr.isPersistent()) {
- if (DEBUG) {
- Slog.v(TAG, "Skipping report for persistent app " + pr);
- }
- return;
- }
-
- int bytes;
- do {
- // get some data
- bytes = Os.read(fd, buf, 0, buf.length);
- if (bytes > 0) {
- if (MORE_DEBUG) {
- String s = new String(buf, 0, bytes, "UTF-8");
- Slog.v(TAG, "READ=" + bytes + "> " + s);
- }
- // did we just get the EOD null byte?
- if (buf[bytes-1] == 0) {
- os.write(buf, 0, bytes-1); // exclude the EOD token
- break;
- }
- // no EOD, so collect it and read more
- os.write(buf, 0, bytes);
- }
- } while (bytes > 0);
-
- // Okay, we've got the report.
- if (DEBUG) Slog.v(TAG, "processing");
-
- // Mark the process record as being a native crash so that the
- // cleanup mechanism knows we're still submitting the report
- // even though the process will vanish as soon as we let
- // debuggerd proceed.
- synchronized (mAm) {
- synchronized (mAm.mProcLock) {
- pr.mErrorState.setCrashing(true);
- pr.mErrorState.setForceCrashReport(true);
- }
- }
-
- // Crash reporting is synchronous but we want to let debuggerd
- // go about it business right away, so we spin off the actual
- // reporting logic on a thread and let it take it's time.
- final String reportString = new String(os.toByteArray(), "UTF-8");
- (new NativeCrashReporter(pr, signal, reportString)).start();
- } else {
- Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid);
- }
- } else {
- Slog.e(TAG, "Bogus pid!");
+ final ProcessRecord pr;
+ synchronized (mAm.mPidsSelfLocked) {
+ pr = mAm.mPidsSelfLocked.get(pid);
}
+ if (pr == null) {
+ Slog.w(TAG, "Couldn't find ProcessRecord for pid " + pid);
+ return;
+ }
+
+ // Don't attempt crash reporting for persistent apps
+ if (pr.isPersistent()) {
+ if (DEBUG) {
+ Slog.v(TAG, "Skipping report for persistent app " + pr);
+ }
+ return;
+ }
+
+ int bytes;
+ do {
+ // get some data
+ bytes = Os.read(fd, buf, 0, buf.length);
+ if (bytes > 0) {
+ if (MORE_DEBUG) {
+ String s = new String(buf, 0, bytes, "UTF-8");
+ Slog.v(TAG, "READ=" + bytes + "> " + s);
+ }
+ // did we just get the EOD null byte?
+ if (buf[bytes - 1] == 0) {
+ os.write(buf, 0, bytes - 1); // exclude the EOD token
+ break;
+ }
+ // no EOD, so collect it and read more
+ os.write(buf, 0, bytes);
+ }
+ } while (bytes > 0);
+
+ // Okay, we've got the report.
+ if (DEBUG) Slog.v(TAG, "processing");
+
+ // Mark the process record as being a native crash so that the
+ // cleanup mechanism knows we're still submitting the report even
+ // though the process will vanish as soon as we let debuggerd
+ // proceed. This isn't relevant for recoverable crashes, as we don't
+ // show the user an "app crashed" dialogue because the app (by
+ // design) didn't crash.
+ if (!gwpAsanRecoverableCrash) {
+ synchronized (mAm) {
+ synchronized (mAm.mProcLock) {
+ pr.mErrorState.setCrashing(true);
+ pr.mErrorState.setForceCrashReport(true);
+ }
+ }
+ }
+
+ // Crash reporting is synchronous but we want to let debuggerd
+ // go about it business right away, so we spin off the actual
+ // reporting logic on a thread and let it take it's time.
+ final String reportString = new String(os.toByteArray(), "UTF-8");
+ (new NativeCrashReporter(pr, signal, gwpAsanRecoverableCrash, reportString)).start();
} catch (Exception e) {
Slog.e(TAG, "Exception dealing with report", e);
// ugh, fail.
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index abddc43..d0607d5 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -105,6 +105,7 @@
import android.os.UserHandle;
import android.os.storage.StorageManagerInternal;
import android.system.Os;
+import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -2328,9 +2329,15 @@
if (!regularZygote) {
// webview and app zygote don't have the permission to create the nodes
- if (Process.createProcessGroup(uid, startResult.pid) < 0) {
- throw new AssertionError("Unable to create process group for " + app.processName
- + " (" + startResult.pid + ")");
+ final int res = Process.createProcessGroup(uid, startResult.pid);
+ if (res < 0) {
+ if (res == -OsConstants.ESRCH) {
+ Slog.e(ActivityManagerService.TAG, "Unable to create process group for "
+ + app.processName + " (" + startResult.pid + ")");
+ } else {
+ throw new AssertionError("Unable to create process group for "
+ + app.processName + " (" + startResult.pid + ")");
+ }
}
}
@@ -2573,7 +2580,10 @@
+ ", " + reason);
app.setPendingStart(false);
killProcessQuiet(pid);
- Process.killProcessGroup(app.uid, app.getPid());
+ final int appPid = app.getPid();
+ if (appPid != 0) {
+ Process.killProcessGroup(app.uid, appPid);
+ }
noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
ApplicationExitInfo.SUBREASON_INVALID_START, reason);
return false;
@@ -5083,6 +5093,17 @@
}
/**
+ * Called by ActivityManagerService when a recoverable native crash occurs.
+ */
+ @GuardedBy("mService")
+ void noteAppRecoverableCrash(final ProcessRecord app) {
+ if (DEBUG_PROCESSES) {
+ Slog.i(TAG, "note: " + app + " has a recoverable native crash");
+ }
+ mAppExitInfoTracker.scheduleNoteAppRecoverableCrash(app);
+ }
+
+ /**
* Called by ActivityManagerService when it decides to kill an application process.
*/
@GuardedBy("mService")
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 8886f0a..b8ff26e 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -98,7 +98,6 @@
DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
DeviceConfig.NAMESPACE_SURFACE_FLINGER_NATIVE_BOOT,
DeviceConfig.NAMESPACE_SWCODEC_NATIVE,
- DeviceConfig.NAMESPACE_TETHERING,
DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE,
DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE_BOOT,
DeviceConfig.NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index a74f4154..210fc910 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1209,6 +1209,9 @@
"LE Audio device addr=" + address + " now available").printLog(TAG));
}
+ // Reset LEA suspend state each time a new sink is connected
+ mAudioSystem.setParameters("LeAudioSuspended=false");
+
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
@@ -1254,6 +1257,9 @@
@GuardedBy("mDevicesLock")
private void makeLeAudioDeviceUnavailableLater(String address, int device, int delayMs) {
+ // prevent any activity on the LEA output to avoid unwanted
+ // reconnection of the sink.
+ mAudioSystem.setParameters("LeAudioSuspended=true");
// the device will be made unavailable later, so consider it disconnected right away
mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
// send the delayed message to make the device unavailable later
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 46ab330..66682cc 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -896,7 +896,7 @@
// Defines the format for the connection "address" for ALSA devices
public static String makeAlsaAddressString(int card, int device) {
- return "card=" + card + ";device=" + device + ";";
+ return "card=" + card + ";device=" + device;
}
public static final class Lifecycle extends SystemService {
@@ -4087,13 +4087,14 @@
return;
}
- // Forcefully set LE audio volume as a workaround, since in some cases
- // (like the outgoing call) the value of 'device' is not DEVICE_OUT_BLE_*
- // even when BLE is connected.
+ // In some cases (like the outgoing or rejected call) the value of 'device' is not
+ // DEVICE_OUT_BLE_* even when BLE is connected. Changing the volume level in such case
+ // may cuase the other devices volume level leaking into the LeAudio device settings.
if (!AudioSystem.isLeAudioDeviceType(device)) {
- Log.w(TAG, "setLeAudioVolumeOnModeUpdate got unexpected device=" + device
- + ", forcing to device=" + AudioSystem.DEVICE_OUT_BLE_HEADSET);
- device = AudioSystem.DEVICE_OUT_BLE_HEADSET;
+ Log.w(TAG, "setLeAudioVolumeOnModeUpdate ignoring invalid device="
+ + device + ", mode=" + mode + ", index=" + index + " maxIndex=" + maxIndex
+ + " streamType=" + streamType);
+ return;
}
if (DEBUG_VOL) {
@@ -7237,6 +7238,7 @@
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_LINE);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+ DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.addAll(AudioSystem.DEVICE_OUT_ALL_USB_SET);
DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.add(AudioSystem.DEVICE_OUT_HDMI);
}
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 6cd42f8..d3b7606 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -477,6 +477,7 @@
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
AudioSystem.setParameters("A2dpSuspended=false");
+ AudioSystem.setParameters("LeAudioSuspended=false");
mDeviceBroker.setBluetoothScoOn(false, "resetBluetoothSco");
}
diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java
index a9e7d4b..c9cdba9 100644
--- a/services/core/java/com/android/server/audio/SpatializerHelper.java
+++ b/services/core/java/com/android/server/audio/SpatializerHelper.java
@@ -106,12 +106,12 @@
};
// Spatializer state machine
- private static final int STATE_UNINITIALIZED = 0;
- private static final int STATE_NOT_SUPPORTED = 1;
- private static final int STATE_DISABLED_UNAVAILABLE = 3;
- private static final int STATE_ENABLED_UNAVAILABLE = 4;
- private static final int STATE_ENABLED_AVAILABLE = 5;
- private static final int STATE_DISABLED_AVAILABLE = 6;
+ /*package*/ static final int STATE_UNINITIALIZED = 0;
+ /*package*/ static final int STATE_NOT_SUPPORTED = 1;
+ /*package*/ static final int STATE_DISABLED_UNAVAILABLE = 3;
+ /*package*/ static final int STATE_ENABLED_UNAVAILABLE = 4;
+ /*package*/ static final int STATE_ENABLED_AVAILABLE = 5;
+ /*package*/ static final int STATE_DISABLED_AVAILABLE = 6;
private int mState = STATE_UNINITIALIZED;
private boolean mFeatureEnabled = false;
@@ -147,9 +147,9 @@
.setSampleRate(48000)
.setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1)
.build();
- // device array to store the routing for the default attributes and format, size 1 because
- // media is never expected to be duplicated
- private static final AudioDeviceAttributes[] ROUTING_DEVICES = new AudioDeviceAttributes[1];
+ // device array to store the routing for the default attributes and format, initialized to
+ // an empty list as routing hasn't been established yet
+ private static ArrayList<AudioDeviceAttributes> sRoutingDevices = new ArrayList<>(0);
//---------------------------------------------------------------
// audio device compatibility / enabled
@@ -184,11 +184,6 @@
SADeviceState.sHeadTrackingEnabledDefault = headTrackingEnabledDefault;
}
- synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) {
- mBinauralSupported = hasBinaural;
- mTransauralSupported = hasTransaural;
- }
-
synchronized void init(boolean effectExpected, @Nullable String settings) {
loglogi("init effectExpected=" + effectExpected);
if (!effectExpected) {
@@ -322,8 +317,7 @@
return;
}
mState = STATE_DISABLED_UNAVAILABLE;
- mASA.getDevicesForAttributes(
- DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES);
+ sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES);
// note at this point mSpat is still not instantiated
}
@@ -365,34 +359,35 @@
case STATE_DISABLED_AVAILABLE:
break;
}
- mASA.getDevicesForAttributes(
- DEFAULT_ATTRIBUTES, false /* forVolume */).toArray(ROUTING_DEVICES);
+
+ sRoutingDevices = getRoutingDevices(DEFAULT_ATTRIBUTES);
// check validity of routing information
- if (ROUTING_DEVICES[0] == null) {
- logloge("onRoutingUpdated: device is null, no Spatial Audio");
+ if (sRoutingDevices.isEmpty()) {
+ logloge("onRoutingUpdated: no device, no Spatial Audio");
setDispatchAvailableState(false);
// not changing the spatializer level as this is likely a transient state
return;
}
+ final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
// is media routed to a new device?
- if (isWireless(ROUTING_DEVICES[0].getType())) {
- addWirelessDeviceIfNew(ROUTING_DEVICES[0]);
+ if (isWireless(currentDevice.getType())) {
+ addWirelessDeviceIfNew(currentDevice);
}
// find if media device enabled / available
- final Pair<Boolean, Boolean> enabledAvailable = evaluateState(ROUTING_DEVICES[0]);
+ final Pair<Boolean, Boolean> enabledAvailable = evaluateState(currentDevice);
boolean able = false;
if (enabledAvailable.second) {
// available for Spatial audio, check w/ effect
- able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, ROUTING_DEVICES);
+ able = canBeSpatializedOnDevice(DEFAULT_ATTRIBUTES, DEFAULT_FORMAT, sRoutingDevices);
loglogi("onRoutingUpdated: can spatialize media 5.1:" + able
- + " on device:" + ROUTING_DEVICES[0]);
+ + " on device:" + currentDevice);
setDispatchAvailableState(able);
} else {
- loglogi("onRoutingUpdated: device:" + ROUTING_DEVICES[0]
+ loglogi("onRoutingUpdated: device:" + currentDevice
+ " not available for Spatial Audio");
setDispatchAvailableState(false);
}
@@ -400,10 +395,10 @@
boolean enabled = able && enabledAvailable.first;
if (enabled) {
loglogi("Enabling Spatial Audio since enabled for media device:"
- + ROUTING_DEVICES[0]);
+ + currentDevice);
} else {
loglogi("Disabling Spatial Audio since disabled for media device:"
- + ROUTING_DEVICES[0]);
+ + currentDevice);
}
if (mSpat != null) {
byte level = enabled ? (byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL
@@ -736,9 +731,13 @@
}
private synchronized boolean canBeSpatializedOnDevice(@NonNull AudioAttributes attributes,
- @NonNull AudioFormat format, @NonNull AudioDeviceAttributes[] devices) {
- if (isDeviceCompatibleWithSpatializationModes(devices[0])) {
- return AudioSystem.canBeSpatialized(attributes, format, devices);
+ @NonNull AudioFormat format, @NonNull ArrayList<AudioDeviceAttributes> devices) {
+ if (devices.isEmpty()) {
+ return false;
+ }
+ if (isDeviceCompatibleWithSpatializationModes(devices.get(0))) {
+ AudioDeviceAttributes[] devArray = new AudioDeviceAttributes[devices.size()];
+ return AudioSystem.canBeSpatialized(attributes, format, devices.toArray(devArray));
}
return false;
}
@@ -1014,10 +1013,13 @@
logd("canBeSpatialized false due to usage:" + attributes.getUsage());
return false;
}
- AudioDeviceAttributes[] devices = new AudioDeviceAttributes[1];
+
// going through adapter to take advantage of routing cache
- mASA.getDevicesForAttributes(
- attributes, false /* forVolume */).toArray(devices);
+ final ArrayList<AudioDeviceAttributes> devices = getRoutingDevices(attributes);
+ if (devices.isEmpty()) {
+ logloge("canBeSpatialized got no device for " + attributes);
+ return false;
+ }
final boolean able = canBeSpatializedOnDevice(attributes, format, devices);
logd("canBeSpatialized usage:" + attributes.getUsage()
+ " format:" + format.toLogFriendlyString() + " returning " + able);
@@ -1148,8 +1150,13 @@
logDeviceState(deviceState, "setHeadTrackerEnabled");
// check current routing to see if it affects the headtracking mode
- if (ROUTING_DEVICES[0] != null && ROUTING_DEVICES[0].getType() == ada.getType()
- && ROUTING_DEVICES[0].getAddress().equals(ada.getAddress())) {
+ if (sRoutingDevices.isEmpty()) {
+ logloge("setHeadTrackerEnabled: no device, bailing");
+ return;
+ }
+ final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
+ if (currentDevice.getType() == ada.getType()
+ && currentDevice.getAddress().equals(ada.getAddress())) {
setDesiredHeadTrackingMode(enabled ? mDesiredHeadTrackingModeWhenEnabled
: Spatializer.HEAD_TRACKING_MODE_DISABLED);
if (enabled && !mHeadTrackerAvailable) {
@@ -1706,10 +1713,11 @@
private int getHeadSensorHandleUpdateTracker() {
int headHandle = -1;
- final AudioDeviceAttributes currentDevice = ROUTING_DEVICES[0];
- if (currentDevice == null) {
+ if (sRoutingDevices.isEmpty()) {
+ logloge("getHeadSensorHandleUpdateTracker: no device, no head tracker");
return headHandle;
}
+ final AudioDeviceAttributes currentDevice = sRoutingDevices.get(0);
UUID routingDeviceUuid = mAudioService.getDeviceSensorUuid(currentDevice);
// We limit only to Sensor.TYPE_HEAD_TRACKER here to avoid confusion
// with gaming sensors. (Note that Sensor.TYPE_ROTATION_VECTOR
@@ -1743,6 +1751,23 @@
return screenHandle;
}
+ /**
+ * Returns routing for the given attributes
+ * @param aa AudioAttributes whose routing is being queried
+ * @return a non-null never-empty list of devices. If the routing query failed, the list
+ * will contain null.
+ */
+ private @NonNull ArrayList<AudioDeviceAttributes> getRoutingDevices(AudioAttributes aa) {
+ final ArrayList<AudioDeviceAttributes> devices = mASA.getDevicesForAttributes(
+ aa, false /* forVolume */);
+ for (AudioDeviceAttributes ada : devices) {
+ if (ada == null) {
+ // invalid entry, reject this routing query by returning an empty list
+ return new ArrayList<>(0);
+ }
+ }
+ return devices;
+ }
private static void loglogi(String msg) {
AudioService.sSpatialLogger.loglogi(msg, TAG);
@@ -1759,4 +1784,13 @@
/*package*/ void clearSADevices() {
mSADevices.clear();
}
+
+ /*package*/ synchronized void forceStateForTest(int state) {
+ mState = state;
+ }
+
+ /*package*/ synchronized void initForTest(boolean hasBinaural, boolean hasTransaural) {
+ mBinauralSupported = hasBinaural;
+ mTransauralSupported = hasTransaural;
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/OWNERS b/services/core/java/com/android/server/biometrics/OWNERS
index cd281e0..1bf2aef 100644
--- a/services/core/java/com/android/server/biometrics/OWNERS
+++ b/services/core/java/com/android/server/biometrics/OWNERS
@@ -6,6 +6,10 @@
jbolinger@google.com
jeffpu@google.com
joshmccloskey@google.com
+diyab@google.com
+austindelgado@google.com
+spdonghao@google.com
+wenhuiy@google.com
firewall@google.com
jasonsfchang@google.com
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 598e2b9..94b67ce 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -452,6 +452,13 @@
return -1;
}
+ if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
+ // If this happens, something in KeyguardUpdateMonitor is wrong. This should only
+ // ever be invoked when the user is encrypted or lockdown.
+ Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
+ return -1;
+ }
+
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFingerprint");
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 1f82961..6d43061 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -41,6 +41,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.BitUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.RingBuffer;
@@ -278,6 +279,11 @@
}
}
+ private boolean hasWifiTransport(Network network) {
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
+ return nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+ }
+
@Override
public synchronized void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader,
byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs) {
@@ -286,12 +292,21 @@
throw new IllegalArgumentException("Prefix " + prefix
+ " required in format <nethandle>:<interface>");
}
+ final long netHandle = Long.parseLong(prefixParts[0]);
+ final Network network = Network.fromNetworkHandle(netHandle);
final WakeupEvent event = new WakeupEvent();
event.iface = prefixParts[1];
event.uid = uid;
event.ethertype = ethertype;
- event.dstHwAddr = MacAddress.fromBytes(dstHw);
+ if (ArrayUtils.isEmpty(dstHw)) {
+ if (hasWifiTransport(network)) {
+ Log.e(TAG, "Empty mac address on WiFi transport, network: " + network);
+ }
+ event.dstHwAddr = null;
+ } else {
+ event.dstHwAddr = MacAddress.fromBytes(dstHw);
+ }
event.srcIp = srcIp;
event.dstIp = dstIp;
event.ipNextHeader = ipNextHeader;
@@ -306,14 +321,12 @@
final BatteryStatsInternal bsi = LocalServices.getService(BatteryStatsInternal.class);
if (bsi != null) {
- final long netHandle = Long.parseLong(prefixParts[0]);
final long elapsedMs = SystemClock.elapsedRealtime() + event.timestampMs
- System.currentTimeMillis();
- bsi.noteCpuWakingNetworkPacket(Network.fromNetworkHandle(netHandle), elapsedMs,
- event.uid);
+ bsi.noteCpuWakingNetworkPacket(network, elapsedMs, event.uid);
}
- final String dstMac = event.dstHwAddr.toString();
+ final String dstMac = String.valueOf(event.dstHwAddr);
FrameworkStatsLog.write(FrameworkStatsLog.PACKET_WAKEUP_OCCURRED,
uid, event.iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index b25206d..4208a12 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -85,6 +85,7 @@
import android.net.NetworkSpecifier;
import android.net.RouteInfo;
import android.net.TelephonyNetworkSpecifier;
+import android.net.TransportInfo;
import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
@@ -107,6 +108,8 @@
import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.ipsec.ike.exceptions.IkeTimeoutException;
+import android.net.vcn.VcnGatewayConnectionConfig;
+import android.net.vcn.VcnTransportInfo;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -152,6 +155,7 @@
import com.android.internal.net.VpnProfile;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.BinderUtils;
+import com.android.net.module.util.LinkPropertiesUtils;
import com.android.net.module.util.NetdUtils;
import com.android.net.module.util.NetworkStackConstants;
import com.android.server.DeviceIdleInternal;
@@ -230,7 +234,35 @@
* <p>If retries have exceeded the length of this array, the last entry in the array will be
* used as a repeating interval.
*/
- private static final long[] IKEV2_VPN_RETRY_DELAYS_SEC = {1L, 2L, 5L, 30L, 60L, 300L, 900L};
+ private static final long[] IKEV2_VPN_RETRY_DELAYS_MS =
+ {1_000L, 2_000L, 5_000L, 30_000L, 60_000L, 300_000L, 900_000L};
+
+ /**
+ * A constant to pass to {@link IkeV2VpnRunner#scheduleStartIkeSession(long)} to mean the
+ * delay should be computed automatically with backoff.
+ */
+ private static final long RETRY_DELAY_AUTO_BACKOFF = -1;
+
+ /**
+ * How long to wait before trying to migrate the IKE connection when NetworkCapabilities or
+ * LinkProperties change in a way that may require migration.
+ *
+ * This delay is useful to avoid multiple migration tries (e.g. when a network changes
+ * both its NC and LP at the same time, e.g. when it first connects) and to minimize the
+ * cases where an old list of addresses is detected for the network.
+ *
+ * In practice, the IKE library reads the LinkProperties of the passed network with
+ * the synchronous {@link ConnectivityManager#getLinkProperties(Network)}, which means in
+ * most cases the race would resolve correctly, but this delay increases the chance that
+ * it correctly is.
+ * Further, using the synchronous method in the IKE library is actually dangerous because
+ * it is racy (it races with {@code IkeNetworkCallbackBase#onLost} and it should be fixed
+ * by using callbacks instead. When that happens, the race within IKE is fixed but the
+ * race between that callback and the one in IkeV2VpnRunner becomes a much bigger problem,
+ * and this delay will be necessary to ensure the correct link address list is used.
+ */
+ private static final long IKE_DELAY_ON_NC_LP_CHANGE_MS = 300;
+
/**
* Largest profile size allowable for Platform VPNs.
*
@@ -424,22 +456,22 @@
private static class CarrierConfigInfo {
public final String mccMnc;
- public final int keepaliveDelayMs;
+ public final int keepaliveDelaySec;
public final int encapType;
public final int ipVersion;
- CarrierConfigInfo(String mccMnc, int keepaliveDelayMs,
+ CarrierConfigInfo(String mccMnc, int keepaliveDelaySec,
int encapType,
int ipVersion) {
this.mccMnc = mccMnc;
- this.keepaliveDelayMs = keepaliveDelayMs;
+ this.keepaliveDelaySec = keepaliveDelaySec;
this.encapType = encapType;
this.ipVersion = ipVersion;
}
@Override
public String toString() {
- return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelayMs=" + keepaliveDelayMs
+ return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelaySec=" + keepaliveDelaySec
+ ", encapType=" + encapType + ", ipVersion=" + ipVersion + "]";
}
}
@@ -619,14 +651,14 @@
/**
* Retrieves the next retry delay
*
- * <p>If retries have exceeded the IKEV2_VPN_RETRY_DELAYS_SEC, the last entry in
+ * <p>If retries have exceeded the size of IKEV2_VPN_RETRY_DELAYS_MS, the last entry in
* the array will be used as a repeating interval.
*/
- public long getNextRetryDelaySeconds(int retryCount) {
- if (retryCount >= IKEV2_VPN_RETRY_DELAYS_SEC.length) {
- return IKEV2_VPN_RETRY_DELAYS_SEC[IKEV2_VPN_RETRY_DELAYS_SEC.length - 1];
+ public long getNextRetryDelayMs(int retryCount) {
+ if (retryCount >= IKEV2_VPN_RETRY_DELAYS_MS.length) {
+ return IKEV2_VPN_RETRY_DELAYS_MS[IKEV2_VPN_RETRY_DELAYS_MS.length - 1];
} else {
- return IKEV2_VPN_RETRY_DELAYS_SEC[retryCount];
+ return IKEV2_VPN_RETRY_DELAYS_MS[retryCount];
}
}
@@ -679,6 +711,14 @@
boolean isIpv4) {
return MtuUtils.getMtu(childProposals, maxMtu, underlyingMtu, isIpv4);
}
+
+ /** Verify the binder calling UID is the one passed in arguments */
+ public void verifyCallingUidAndPackage(Context context, String packageName, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ if (getAppUid(context, packageName, userId) != callingUid) {
+ throw new SecurityException(packageName + " does not belong to uid " + callingUid);
+ }
+ }
}
@VisibleForTesting
@@ -726,7 +766,7 @@
mUserManager = mContext.getSystemService(UserManager.class);
mPackage = VpnConfig.LEGACY_VPN;
- mOwnerUID = getAppUid(mPackage, mUserId);
+ mOwnerUID = getAppUid(mContext, mPackage, mUserId);
mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(mPackage);
try {
@@ -823,7 +863,7 @@
}
/**
- * Chooses whether to force all connections to go though VPN.
+ * Chooses whether to force all connections to go through VPN.
*
* Used to enable/disable legacy VPN lockdown.
*
@@ -831,7 +871,7 @@
* {@link #setAlwaysOnPackage(String, boolean, List<String>)}; previous settings from calling
* that function will be replaced and saved with the always-on state.
*
- * @param lockdown whether to prevent all traffic outside of a VPN.
+ * @param lockdown whether to prevent all traffic outside of the VPN.
*/
public synchronized void setLockdown(boolean lockdown) {
enforceControlPermissionOrInternalCaller();
@@ -969,15 +1009,21 @@
// Allow VpnManager app to temporarily run background services to handle this error.
// If an app requires anything beyond this grace period, they MUST either declare
// themselves as a foreground service, or schedule a job/workitem.
- DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal();
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
- VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN,
- "VpnManager event");
+ final long token = Binder.clearCallingIdentity();
try {
- return mUserIdContext.startService(intent) != null;
- } catch (RuntimeException e) {
- Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e);
- return false;
+ final DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal();
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
+ VPN_MANAGER_EVENT_ALLOWLIST_DURATION_MS, mUserId, false, REASON_VPN,
+ "VpnManager event");
+
+ try {
+ return mUserIdContext.startService(intent) != null;
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Service of VpnManager app " + intent + " failed to start", e);
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
@@ -1102,6 +1148,7 @@
mAlwaysOn = false;
}
+ final boolean oldLockdownState = mLockdown;
mLockdown = (mAlwaysOn && lockdown);
mLockdownAllowlist = (mLockdown && lockdownAllowlist != null)
? Collections.unmodifiableList(new ArrayList<>(lockdownAllowlist))
@@ -1112,6 +1159,13 @@
if (isCurrentPreparedPackage(packageName)) {
updateAlwaysOnNotification(mNetworkInfo.getDetailedState());
setVpnForcedLocked(mLockdown);
+
+ // Lockdown forces the VPN to be non-bypassable (see #agentConnect) because it makes
+ // no sense for a VPN to be bypassable when connected but not when not connected.
+ // As such, changes in lockdown need to restart the agent.
+ if (mNetworkAgent != null && oldLockdownState != mLockdown) {
+ startNewNetworkAgent(mNetworkAgent, "Lockdown mode changed");
+ }
} else {
// Prepare this app. The notification will update as a side-effect of updateState().
// It also calls setVpnForcedLocked().
@@ -1349,7 +1403,8 @@
// We can't just check that packageName matches mPackage, because if the app was uninstalled
// and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the
// calling package may not be the same as the prepared package. Check both UID and package.
- return getAppUid(packageName, mUserId) == mOwnerUID && mPackage.equals(packageName);
+ return getAppUid(mContext, packageName, mUserId) == mOwnerUID
+ && mPackage.equals(packageName);
}
/** Prepare the VPN for the given package. Does not perform permission checks. */
@@ -1390,7 +1445,7 @@
Log.i(TAG, "Switched from " + mPackage + " to " + newPackage);
mPackage = newPackage;
- mOwnerUID = getAppUid(newPackage, mUserId);
+ mOwnerUID = getAppUid(mContext, newPackage, mUserId);
mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage);
try {
mNms.allowProtect(mOwnerUID);
@@ -1411,7 +1466,7 @@
// Check if the caller is authorized.
enforceControlPermissionOrInternalCaller();
- final int uid = getAppUid(packageName, mUserId);
+ final int uid = getAppUid(mContext, packageName, mUserId);
if (uid == -1 || VpnConfig.LEGACY_VPN.equals(packageName)) {
// Authorization for nonexistent packages (or fake ones) can't be updated.
return false;
@@ -1491,11 +1546,11 @@
|| isVpnServicePreConsented(context, packageName);
}
- private int getAppUid(final String app, final int userId) {
+ private static int getAppUid(final Context context, final String app, final int userId) {
if (VpnConfig.LEGACY_VPN.equals(app)) {
return Process.myUid();
}
- PackageManager pm = mContext.getPackageManager();
+ PackageManager pm = context.getPackageManager();
final long token = Binder.clearCallingIdentity();
try {
return pm.getPackageUidAsUser(app, userId);
@@ -1624,6 +1679,10 @@
*/
private boolean updateLinkPropertiesInPlaceIfPossible(NetworkAgent agent, VpnConfig oldConfig) {
// NetworkAgentConfig cannot be updated without registering a new NetworkAgent.
+ // Strictly speaking, bypassability is affected by lockdown and therefore it's possible
+ // it doesn't actually change even if mConfig.allowBypass changed. It might be theoretically
+ // possible to do handover in this case, but this is far from obvious to VPN authors and
+ // it's simpler if the rule is just "can't update in place if you change allow bypass".
if (oldConfig.allowBypass != mConfig.allowBypass) {
Log.i(TAG, "Handover not possible due to changes to allowBypass");
return false;
@@ -1665,10 +1724,11 @@
mLegacyState = LegacyVpnInfo.STATE_CONNECTING;
updateState(DetailedState.CONNECTING, "agentConnect");
+ final boolean bypassable = mConfig.allowBypass && !mLockdown;
final NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig.Builder()
.setLegacyType(ConnectivityManager.TYPE_VPN)
.setLegacyTypeName("VPN")
- .setBypassableVpn(mConfig.allowBypass && !mLockdown)
+ .setBypassableVpn(bypassable)
.setVpnRequiresValidation(mConfig.requiresInternetValidation)
.setLocalRoutesExcludedForVpn(mConfig.excludeLocalRoutes)
.build();
@@ -1682,7 +1742,7 @@
capsBuilder.setTransportInfo(new VpnTransportInfo(
getActiveVpnType(),
mConfig.session,
- mConfig.allowBypass,
+ bypassable,
expensive));
// Only apps targeting Q and above can explicitly declare themselves as metered.
@@ -1713,6 +1773,10 @@
Binder.restoreCallingIdentity(token);
}
updateState(DetailedState.CONNECTED, "agentConnect");
+ if (isIkev2VpnRunner()) {
+ final IkeSessionWrapper session = ((IkeV2VpnRunner) mVpnRunner).mSession;
+ if (null != session) session.setUnderpinnedNetwork(mNetworkAgent.getNetwork());
+ }
}
private static boolean areLongLivedTcpConnectionsExpensive(@NonNull VpnRunner runner) {
@@ -1907,7 +1971,7 @@
private SortedSet<Integer> getAppsUids(List<String> packageNames, int userId) {
SortedSet<Integer> uids = new TreeSet<>();
for (String app : packageNames) {
- int uid = getAppUid(app, userId);
+ int uid = getAppUid(mContext, app, userId);
if (uid != -1) uids.add(uid);
// TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
// ConnectivityServiceTest.
@@ -3226,7 +3290,6 @@
prepareStatusIntent();
}
agentConnect(this::onValidationStatus);
- mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork());
return; // Link properties are already sent.
} else {
// Underlying networks also set in agentConnect()
@@ -3343,7 +3406,6 @@
if (!removedAddrs.isEmpty()) {
startNewNetworkAgent(
mNetworkAgent, "MTU too low for IPv6; restarting network agent");
- mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork());
for (LinkAddress removed : removedAddrs) {
mTunnelIface.removeAddress(
@@ -3391,6 +3453,7 @@
* consistency of the Ikev2VpnRunner fields.
*/
public void onDefaultNetworkChanged(@NonNull Network network) {
+ mEventChanges.log("[UnderlyingNW] Default network changed to " + network);
Log.d(TAG, "onDefaultNetworkChanged: " + network);
// If there is a new default network brought up, cancel the retry task to prevent
@@ -3496,39 +3559,63 @@
}
private int guessEspIpVersionForNetwork() {
- final CarrierConfigInfo carrierconfig = getCarrierConfig();
+ if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) {
+ Log.d(TAG, "Running over VCN, esp IP version is auto");
+ return ESP_IP_VERSION_AUTO;
+ }
+ final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork();
final int ipVersion = (carrierconfig != null)
? carrierconfig.ipVersion : ESP_IP_VERSION_AUTO;
if (carrierconfig != null) {
- Log.d(TAG, "Get customized IP version(" + ipVersion + ") on SIM("
+ Log.d(TAG, "Get customized IP version (" + ipVersion + ") on SIM (mccmnc="
+ carrierconfig.mccMnc + ")");
}
return ipVersion;
}
private int guessEspEncapTypeForNetwork() {
- final CarrierConfigInfo carrierconfig = getCarrierConfig();
+ if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) {
+ Log.d(TAG, "Running over VCN, encap type is auto");
+ return ESP_ENCAP_TYPE_AUTO;
+ }
+ final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork();
final int encapType = (carrierconfig != null)
? carrierconfig.encapType : ESP_ENCAP_TYPE_AUTO;
if (carrierconfig != null) {
- Log.d(TAG, "Get customized encap type(" + encapType + ") on SIM("
+ Log.d(TAG, "Get customized encap type (" + encapType + ") on SIM (mccmnc="
+ carrierconfig.mccMnc + ")");
}
return encapType;
}
+
private int guessNattKeepaliveTimerForNetwork() {
- final CarrierConfigInfo carrierconfig = getCarrierConfig();
- final int natKeepalive = (carrierconfig != null)
- ? carrierconfig.keepaliveDelayMs : AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+ final TransportInfo transportInfo = mUnderlyingNetworkCapabilities.getTransportInfo();
+ if (transportInfo instanceof VcnTransportInfo) {
+ final int nattKeepaliveSec =
+ ((VcnTransportInfo) transportInfo).getMinUdpPort4500NatTimeoutSeconds();
+ Log.d(TAG, "Running over VCN, keepalive timer : " + nattKeepaliveSec + "s");
+ if (VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET
+ != nattKeepaliveSec) {
+ return nattKeepaliveSec;
+ }
+ // else fall back to carrier config, if any
+ }
+ final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork();
+ final int nattKeepaliveSec = (carrierconfig != null)
+ ? carrierconfig.keepaliveDelaySec : AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
if (carrierconfig != null) {
- Log.d(TAG, "Get customized keepalive(" + natKeepalive + ") on SIM("
+ Log.d(TAG, "Get customized keepalive (" + nattKeepaliveSec + "s) on SIM (mccmnc="
+ carrierconfig.mccMnc + ")");
}
- return natKeepalive;
+ return nattKeepaliveSec;
}
- private CarrierConfigInfo getCarrierConfig() {
+ /**
+ * Returns the carrier config for the underlying network, or null if not a cell network.
+ */
+ @Nullable
+ private CarrierConfigInfo getCarrierConfigForUnderlyingNetwork() {
final int subId = getCellSubIdForNetworkCapabilities(mUnderlyingNetworkCapabilities);
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(TAG, "Underlying network is not a cellular network");
@@ -3590,8 +3677,11 @@
encapType = IkeSessionParams.ESP_ENCAP_TYPE_NONE;
break;
default:
- ipVersion = IkeSessionParams.ESP_IP_VERSION_AUTO;
- encapType = IkeSessionParams.ESP_ENCAP_TYPE_AUTO;
+ // By default, PREFERRED_IKE_PROTOCOL_IPV4_UDP is used for safety. This is
+ // because some carriers' networks do not support IPv6 very well, and using
+ // IPv4 can help to prevent problems.
+ ipVersion = IkeSessionParams.ESP_IP_VERSION_IPV4;
+ encapType = IkeSessionParams.ESP_ENCAP_TYPE_UDP;
break;
}
return new CarrierConfigInfo(mccMnc, natKeepalive, encapType, ipVersion);
@@ -3621,13 +3711,14 @@
final VpnTransportInfo info = new VpnTransportInfo(
getActiveVpnType(),
mConfig.session,
- mConfig.allowBypass,
+ mConfig.allowBypass && !mLockdown,
areLongLivedTcpConnectionsExpensive(keepaliveDelaySec));
final boolean ncUpdateRequired = !info.equals(mNetworkCapabilities.getTransportInfo());
if (ncUpdateRequired) {
mNetworkCapabilities = new NetworkCapabilities.Builder(mNetworkCapabilities)
.setTransportInfo(info)
.build();
+ mEventChanges.log("[VPNRunner] Update agent caps " + mNetworkCapabilities);
doSendNetworkCapabilities(mNetworkAgent, mNetworkCapabilities);
}
}
@@ -3664,6 +3755,7 @@
private void startIkeSession(@NonNull Network underlyingNetwork) {
Log.d(TAG, "Start new IKE session on network " + underlyingNetwork);
+ mEventChanges.log("[IKE] Start IKE session over " + underlyingNetwork);
try {
// Clear mInterface to prevent Ikev2VpnRunner being cleared when
@@ -3709,13 +3801,20 @@
}
}
- private void scheduleRetryNewIkeSession() {
+ /**
+ * Schedule starting an IKE session.
+ * @param delayMs the delay after which to try starting the session. This should be
+ * RETRY_DELAY_AUTO_BACKOFF for automatic retries with backoff.
+ */
+ private void scheduleStartIkeSession(final long delayMs) {
if (mScheduledHandleRetryIkeSessionFuture != null) {
Log.d(TAG, "There is a pending retrying task, skip the new retrying task");
return;
}
- final long retryDelay = mDeps.getNextRetryDelaySeconds(mRetryCount++);
- Log.d(TAG, "Retry new IKE session after " + retryDelay + " seconds.");
+ final long retryDelayMs = RETRY_DELAY_AUTO_BACKOFF != delayMs
+ ? delayMs
+ : mDeps.getNextRetryDelayMs(mRetryCount++);
+ Log.d(TAG, "Retry new IKE session after " + retryDelayMs + " milliseconds.");
// If the default network is lost during the retry delay, the mActiveNetwork will be
// null, and the new IKE session won't be established until there is a new default
// network bringing up.
@@ -3726,7 +3825,7 @@
// Reset mScheduledHandleRetryIkeSessionFuture since it's already run on
// executor thread.
mScheduledHandleRetryIkeSessionFuture = null;
- }, retryDelay, TimeUnit.SECONDS);
+ }, retryDelayMs, TimeUnit.MILLISECONDS);
}
/** Called when the NetworkCapabilities of underlying network is changed */
@@ -3735,20 +3834,26 @@
+ mUnderlyingNetworkCapabilities + " to " + nc);
final NetworkCapabilities oldNc = mUnderlyingNetworkCapabilities;
mUnderlyingNetworkCapabilities = nc;
- if (oldNc == null) {
- // A new default network is available.
- startOrMigrateIkeSession(mActiveNetwork);
- } else if (!nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) {
- // Renew carrierConfig values.
- maybeMigrateIkeSessionAndUpdateVpnTransportInfo(mActiveNetwork);
+ if (oldNc == null || !nc.getSubscriptionIds().equals(oldNc.getSubscriptionIds())) {
+ // A new default network is available, or the subscription has changed.
+ // Try to migrate the session, or failing that, start a new one.
+ scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS);
}
}
/** Called when the LinkProperties of underlying network is changed */
public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) {
- mEventChanges.log("[UnderlyingNW] Lp changed from "
- + mUnderlyingLinkProperties + " to " + lp);
+ final LinkProperties oldLp = mUnderlyingLinkProperties;
+ mEventChanges.log("[UnderlyingNW] Lp changed from " + oldLp + " to " + lp);
mUnderlyingLinkProperties = lp;
+ if (oldLp == null || !LinkPropertiesUtils.isIdenticalAllLinkAddresses(oldLp, lp)) {
+ // If some of the link addresses changed, the IKE session may need to be migrated
+ // or restarted, for example if the available IP families have changed or if the
+ // source address used has gone away. See IkeConnectionController#onNetworkSetByUser
+ // and IkeConnectionController#selectAndSetRemoteAddress for where this ends up
+ // re-evaluating the session.
+ scheduleStartIkeSession(IKE_DELAY_ON_NC_LP_CHANGE_MS);
+ }
}
class VpnConnectivityDiagnosticsCallback
@@ -3778,6 +3883,7 @@
}
public void onValidationStatus(int status) {
+ mEventChanges.log("[Validation] validation status " + status);
if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
// No data stall now. Reset it.
mExecutor.execute(() -> {
@@ -3818,6 +3924,7 @@
* consistency of the Ikev2VpnRunner fields.
*/
public void onDefaultNetworkLost(@NonNull Network network) {
+ mEventChanges.log("[UnderlyingNW] Network lost " + network);
// If the default network is torn down, there is no need to call
// startOrMigrateIkeSession() since it will always check if there is an active network
// can be used or not.
@@ -3936,6 +4043,8 @@
* consistency of the Ikev2VpnRunner fields.
*/
public void onSessionLost(int token, @Nullable Exception exception) {
+ mEventChanges.log("[IKE] Session lost on network " + mActiveNetwork
+ + (null == exception ? "" : " reason " + exception.getMessage()));
Log.d(TAG, "onSessionLost() called for token " + token);
if (!isActiveToken(token)) {
@@ -4022,7 +4131,7 @@
markFailedAndDisconnect(exception);
return;
} else {
- scheduleRetryNewIkeSession();
+ scheduleStartIkeSession(RETRY_DELAY_AUTO_BACKOFF);
}
// Close all obsolete state, but keep VPN alive incase a usable network comes up.
@@ -4092,6 +4201,7 @@
* consistency of the Ikev2VpnRunner fields.
*/
private void disconnectVpnRunner() {
+ mEventChanges.log("[VPNRunner] Disconnect runner, underlying network" + mActiveNetwork);
mActiveNetwork = null;
mUnderlyingNetworkCapabilities = null;
mUnderlyingLinkProperties = null;
@@ -4458,10 +4568,7 @@
}
private void verifyCallingUidAndPackage(String packageName) {
- final int callingUid = Binder.getCallingUid();
- if (getAppUid(packageName, mUserId) != callingUid) {
- throw new SecurityException(packageName + " does not belong to uid " + callingUid);
- }
+ mDeps.verifyCallingUidAndPackage(mContext, packageName, mUserId);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 54189bf7..237485b 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1670,9 +1670,11 @@
// TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
// done in HighBrightnessModeController.
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
- && (mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
- && (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0) {
- // We want to scale HDR brightness level with the SDR level
+ && (mBrightnessReasonTemp.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
+ && (mBrightnessReasonTemp.modifier & BrightnessReason.MODIFIER_LOW_POWER)
+ == 0) {
+ // We want to scale HDR brightness level with the SDR level, we also need to restore
+ // SDR brightness immediately when entering dim or low power mode.
animateValue = mHbmController.getHdrBrightnessValue();
}
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index 73131a1..06dd500 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -300,8 +300,11 @@
}
public boolean setBrightness(DisplayDevice displayDevice, float brightness) {
+ if (displayDevice == null || !displayDevice.hasStableUniqueId()) {
+ return false;
+ }
final String displayDeviceUniqueId = displayDevice.getUniqueId();
- if (!displayDevice.hasStableUniqueId() || displayDeviceUniqueId == null) {
+ if (displayDeviceUniqueId == null) {
return false;
}
final DisplayState state = getDisplayState(displayDeviceUniqueId, true);
diff --git a/services/core/java/com/android/server/infra/OWNERS b/services/core/java/com/android/server/infra/OWNERS
index 0466d8a..4fea05d 100644
--- a/services/core/java/com/android/server/infra/OWNERS
+++ b/services/core/java/com/android/server/infra/OWNERS
@@ -1,3 +1,3 @@
# Bug component: 655446
-include /core/java/android/service/cloudsearch/OWNERS
+srazdan@google.com
diff --git a/services/core/java/com/android/server/inputmethod/OWNERS b/services/core/java/com/android/server/inputmethod/OWNERS
index 00cd700..6e5eb56 100644
--- a/services/core/java/com/android/server/inputmethod/OWNERS
+++ b/services/core/java/com/android/server/inputmethod/OWNERS
@@ -1,8 +1,8 @@
set noparent
-ogunwale@google.com
+roosa@google.com
yukawa@google.com
tarandeep@google.com
-lumark@google.com
-roosa@google.com
-wilsonwu@google.com
+
+ogunwale@google.com #{LAST_RESORT_SUGGESTION}
+jjaggi@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 1235352..f0aff2a 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -300,6 +300,7 @@
public void deliverOnFlushComplete(int requestCode) throws PendingIntent.CanceledException {
BroadcastOptions options = BroadcastOptions.makeBasic();
options.setDontSendToRestrictedApps(true);
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_FLUSH_COMPLETE, requestCode),
null, null, null, options.toBundle());
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index dcf1906..d285337 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -220,6 +220,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
@@ -801,6 +802,16 @@
}
return buckets;
}
+
+ /** Require IPC call. Don't call when holding a lock. */
+ int getDefaultDataSubId() {
+ return SubscriptionManager.getDefaultDataSubscriptionId();
+ }
+
+ /** Require IPC call. Don't call when holding a lock. */
+ int getActivateDataSubId() {
+ return SubscriptionManager.getActiveDataSubscriptionId();
+ }
}
@VisibleForTesting
@@ -828,7 +839,7 @@
mSuppressDefaultPolicy = suppressDefaultPolicy;
mDeps = Objects.requireNonNull(deps, "missing Dependencies");
-
+ mActiveDataSubIdListener = new ActiveDataSubIdListener();
mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy");
mAppOps = context.getSystemService(AppOpsManager.class);
@@ -1088,6 +1099,10 @@
}
});
+ // Listen for active data sub Id change, upon which data notifications is shown/hidden.
+ mContext.getSystemService(TelephonyManager.class).registerTelephonyCallback(executor,
+ mActiveDataSubIdListener);
+
// tell systemReady() that the service has been initialized
initCompleteSignal.countDown();
} finally {
@@ -1257,6 +1272,38 @@
};
/**
+ * Listener that watches for active data sub Id change, upon which data notifications are
+ * shown/hidden.
+ */
+ private final ActiveDataSubIdListener mActiveDataSubIdListener;
+ private class ActiveDataSubIdListener extends TelephonyCallback implements
+ TelephonyCallback.ActiveDataSubscriptionIdListener {
+ /**
+ * In most cases active data sub is the same as the default data sub, but if user enabled
+ * auto data switch {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH},
+ * active data sub could be the non-default data sub.
+ *
+ * If the listener is initialized before the phone process is up, the IPC call to the
+ * static method of SubscriptionManager lead to INVALID_SUBSCRIPTION_ID to be returned,
+ * indicating the phone process is unable to determine a valid data sub Id at this point, in
+ * which case no data notifications should be shown anyway. Later on when an active data
+ * sub is known, notifications will be re-evaluated by this callback.
+ */
+ private int mDefaultDataSubId = mDeps.getDefaultDataSubId();
+ private int mActiveDataSubId = mDeps.getActivateDataSubId();
+ // Only listen to active data sub change is sufficient because default data sub change
+ // leads to active data sub change as well.
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mActiveDataSubId = subId;
+ mDefaultDataSubId = mDeps.getDefaultDataSubId();
+ synchronized (mNetworkPoliciesSecondLock) {
+ updateNotificationsNL();
+ }
+ }
+ }
+
+ /**
* Listener that watches for {@link NetworkStatsManager} updates, which
* NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}.
*/
@@ -1445,6 +1492,9 @@
// ignore policies that aren't relevant to user
if (subId == INVALID_SUBSCRIPTION_ID) continue;
+ // ignore if the data sub is neither default nor active for data at the moment.
+ if (subId != mActiveDataSubIdListener.mDefaultDataSubId
+ && subId != mActiveDataSubIdListener.mActiveDataSubId) continue;
if (!policy.hasCycle()) continue;
final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 65bd3f1..0f13c2c 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -108,7 +108,7 @@
@VisibleForTesting
static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000;
@VisibleForTesting
- static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 50000;
+ static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 6000;
private static final int NOTIFICATION_PREFERENCES_PULL_LIMIT = 1000;
private static final int NOTIFICATION_CHANNEL_PULL_LIMIT = 2000;
diff --git a/services/core/java/com/android/server/pm/ApkChecksums.java b/services/core/java/com/android/server/pm/ApkChecksums.java
index ffe0ca0..b00cc1a 100644
--- a/services/core/java/com/android/server/pm/ApkChecksums.java
+++ b/services/core/java/com/android/server/pm/ApkChecksums.java
@@ -40,8 +40,6 @@
import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.pm.parsing.result.ParseResult;
import android.content.pm.parsing.result.ParseTypeImpl;
-import android.os.Environment;
-import android.os.FileUtils;
import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -638,18 +636,9 @@
return null;
}
- private static boolean containsFile(File dir, String filePath) {
- if (dir == null) {
- return false;
- }
- return FileUtils.contains(dir.getAbsolutePath(), filePath);
- }
-
private static ApkChecksum extractHashFromFS(String split, String filePath) {
// verity first
- // Skip /product folder.
- // TODO(b/231354111): remove this hack once we are allowed to change SELinux rules.
- if (!containsFile(Environment.getProductDirectory(), filePath)) {
+ if (VerityUtils.hasFsverity(filePath)) {
byte[] verityHash = VerityUtils.getFsverityDigest(filePath);
if (verityHash != null) {
return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, verityHash);
diff --git a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
index b4bcd5b..5de1559 100644
--- a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
+++ b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
@@ -61,7 +61,7 @@
private static final String AVC_PREFIX = "type=" + AUDIT_AVC + " ";
private static final Pattern EXECUTE_NATIVE_AUDIT_PATTERN =
- Pattern.compile(".*\\bavc: granted \\{ execute(?:_no_trans|) \\} .*"
+ Pattern.compile(".*\\bavc: +granted +\\{ execute(?:_no_trans|) \\} .*"
+ "\\bpath=(?:\"([^\" ]*)\"|([0-9A-F]+)) .*"
+ "\\bscontext=u:r:untrusted_app(?:_25|_27)?:.*"
+ "\\btcontext=u:object_r:app_data_file:.*"
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 0de44bc..3dac305 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -94,6 +94,7 @@
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.ApplicationPackageManager;
+import android.app.BroadcastOptions;
import android.app.backup.IBackupManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -641,7 +642,10 @@
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
PackageManager.installStatusToPublicStatus(returnCode));
try {
- target.sendIntent(context, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ target.sendIntent(context, 0, fillIn, null /* onFinished*/, null /* handler */,
+ null /* requiredPermission */, options.toBundle());
} catch (IntentSender.SendIntentException ignored) {
}
}
@@ -2425,10 +2429,10 @@
// will be null whereas dataOwnerPkg will contain information about the package
// which was uninstalled while keeping its data.
AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName);
+ PackageSetting dataOwnerPs = mPm.mSettings.getPackageLPr(packageName);
if (dataOwnerPkg == null) {
- PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
- if (ps != null) {
- dataOwnerPkg = ps.getPkg();
+ if (dataOwnerPs != null) {
+ dataOwnerPkg = dataOwnerPs.getPkg();
}
}
@@ -2456,6 +2460,7 @@
if (dataOwnerPkg != null && !dataOwnerPkg.isSdkLibrary()) {
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
dataOwnerPkg.isDebuggable())) {
+ // Downgrade is not permitted; a lower version of the app will not be allowed
try {
PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
} catch (PackageManagerException e) {
@@ -2464,6 +2469,28 @@
return Pair.create(
PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
}
+ } else if (dataOwnerPs.isSystem()) {
+ // Downgrade is permitted, but system apps can't be downgraded below
+ // the version preloaded onto the system image
+ final PackageSetting disabledPs = mPm.mSettings.getDisabledSystemPkgLPr(
+ dataOwnerPs);
+ if (disabledPs != null) {
+ dataOwnerPkg = disabledPs.getPkg();
+ }
+ if (!Build.IS_DEBUGGABLE && !dataOwnerPkg.isDebuggable()) {
+ // Only restrict non-debuggable builds and non-debuggable version of the app
+ try {
+ PackageManagerServiceUtils.checkDowngrade(dataOwnerPkg, pkgLite);
+ } catch (PackageManagerException e) {
+ String errorMsg =
+ "System app: " + packageName + " cannot be downgraded to"
+ + " older than its preloaded version on the system"
+ + " image. " + e.getMessage();
+ Slog.w(TAG, errorMsg);
+ return Pair.create(
+ PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
+ }
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index bb23d89d..02cf433 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -27,6 +27,7 @@
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PackageDeleteObserver;
@@ -1360,7 +1361,10 @@
PackageInstaller.STATUS_PENDING_USER_ACTION);
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException ignored) {
}
}
@@ -1385,7 +1389,10 @@
PackageManager.deleteStatusToString(returnCode, msg));
fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
try {
- mTarget.sendIntent(mContext, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ mTarget.sendIntent(mContext, 0, fillIn, null /* onFinished*/,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (SendIntentException ignored) {
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 7c2e3ea..1823de8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -54,6 +54,7 @@
import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyEventLogger;
@@ -4274,7 +4275,10 @@
fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_PENDING_USER_ACTION);
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
try {
- target.sendIntent(context, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ target.sendIntent(context, 0, fillIn, null /* onFinished */,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (IntentSender.SendIntentException ignored) {
}
}
@@ -4315,7 +4319,10 @@
}
}
try {
- target.sendIntent(context, 0, fillIn, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ target.sendIntent(context, 0, fillIn, null /* onFinished */,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (IntentSender.SendIntentException ignored) {
}
}
@@ -4349,7 +4356,10 @@
intent.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, "Staging Image Not Ready");
}
try {
- target.sendIntent(context, 0, intent, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ target.sendIntent(context, 0, intent, null /* onFinished */,
+ null /* handler */, null /* requiredPermission */, options.toBundle());
} catch (IntentSender.SendIntentException ignored) {
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8d2714c..4786037 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -53,6 +53,7 @@
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.ApplicationPackageManager;
+import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.admin.IDevicePolicyManager;
import android.app.admin.SecurityLog;
@@ -4798,7 +4799,11 @@
}
if (pi != null) {
try {
- pi.sendIntent(null, success ? 1 : 0, null, null, null);
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityLaunchAllowed(false);
+ pi.sendIntent(null, success ? 1 : 0, null /* intent */,
+ null /* onFinished*/, null /* handler */,
+ null /* requiredPermission */, options.toBundle());
} catch (SendIntentException e) {
Slog.w(TAG, e);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 714be18..be719e3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -38,7 +38,7 @@
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
+import android.compat.annotation.Disabled;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -155,7 +155,7 @@
* allow 3P apps to trigger internal-only functionality.
*/
@ChangeId
- @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ @Disabled /* Revert enforcement: b/274147456 */
private static final long ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS = 161252188;
/**
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 890c891..8507ad0 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -430,6 +430,7 @@
@NonNull List<ShortcutInfo> changedShortcuts) {
Preconditions.checkArgument(newShortcut.isEnabled(),
"pushDynamicShortcuts() cannot publish disabled shortcuts");
+ ensureShortcutCountBeforePush();
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
@@ -437,7 +438,7 @@
final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
boolean deleted = false;
- if (oldShortcut == null) {
+ if (oldShortcut == null || !oldShortcut.isDynamic()) {
final ShortcutService service = mShortcutUser.mService;
final int maxShortcuts = service.getMaxActivityShortcuts();
@@ -446,18 +447,12 @@
final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
- Slog.e(TAG, "Error pushing shortcut. There are already "
- + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
- + " shortcuts limit when pushing the new shortcut " + newShortcut
- + ". Id of shortcuts currently available in system memory are "
- + activityShortcuts.stream().map(ShortcutInfo::getId)
- .collect(Collectors.joining(",", "[", "]")));
- // TODO: This should not have happened. If it does, identify the root cause where
- // possible, otherwise bail-out early to prevent memory issue.
+ // Root cause was discovered in b/233155034, so this should not be happening.
+ service.wtf("Error pushing shortcut. There are already "
+ + activityShortcuts.size() + " shortcuts.");
}
if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
// Max has reached. Delete the shortcut with lowest rank.
-
// Sort by isManifestShortcut() and getRank().
Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
@@ -473,7 +468,8 @@
deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
/*ignorePersistedShortcuts=*/ true) != null;
}
- } else {
+ }
+ if (oldShortcut != null) {
// It's an update case.
// Make sure the target is updatable. (i.e. should be mutable.)
oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@
return deleted;
}
+ private void ensureShortcutCountBeforePush() {
+ final ShortcutService service = mShortcutUser.mService;
+ // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
+ final int maxShortcutPerApp = service.getMaxAppShortcuts();
+ synchronized (mLock) {
+ final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
+ !si.isPinned()).collect(Collectors.toList());
+ if (appShortcuts.size() >= maxShortcutPerApp) {
+ // Max has reached. Removes shortcuts until they fall within the hard cap.
+ // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
+ Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
+
+ while (appShortcuts.size() >= maxShortcutPerApp) {
+ final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
+ if (shortcut.isDeclaredInManifest()) {
+ // All shortcuts are manifest shortcuts and cannot be removed.
+ throw new IllegalArgumentException(getPackageName() + " has published "
+ + appShortcuts.size() + " manifest shortcuts across different"
+ + " activities.");
+ }
+ forceDeleteShortcutInner(shortcut.getId());
+ }
+ }
+ }
+ }
+
/**
* Remove all shortcuts that aren't pinned, cached nor dynamic.
*
@@ -1367,6 +1389,61 @@
};
/**
+ * To sort by isManifestShortcut(), isDynamic(), getRank() and
+ * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
+ * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
+ *
+ * This is used to decide which shortcuts to remove when the total number of shortcuts retained
+ * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
+ *
+ * (Note the number of manifest shortcuts is always <= the max number, because if there are
+ * more, ShortcutParser would ignore the rest.)
+ */
+ final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
+ ShortcutInfo b) -> {
+ if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+ return -1;
+ }
+ if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+ return 1;
+ }
+ if (a.isDynamic() && b.isDynamic()) {
+ return Integer.compare(a.getRank(), b.getRank());
+ }
+ if (a.isDynamic()) {
+ return -1;
+ }
+ if (b.isDynamic()) {
+ return 1;
+ }
+ if (a.isCached() && b.isCached()) {
+ // if both shortcuts are cached, prioritize shortcuts cached by people tile,
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+ return 1;
+ }
+ // followed by bubbles.
+ if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return -1;
+ } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+ && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+ return 1;
+ }
+ }
+ if (a.isCached()) {
+ return -1;
+ }
+ if (b.isCached()) {
+ return 1;
+ }
+ return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
+ };
+
+ /**
* Build a list of shortcuts for each target activity and return as a map. The result won't
* contain "floating" shortcuts because they don't belong on any activities.
*/
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 0b20683..f303fed 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -181,6 +181,9 @@
static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
@VisibleForTesting
+ static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;
+
+ @VisibleForTesting
static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
@VisibleForTesting
@@ -257,6 +260,11 @@
String KEY_MAX_SHORTCUTS = "max_shortcuts";
/**
+ * Key name for the max shortcuts can be retained in system ram per app. (int)
+ */
+ String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";
+
+ /**
* Key name for icon compression quality, 0-100.
*/
String KEY_ICON_QUALITY = "icon_quality";
@@ -329,11 +337,16 @@
new SparseArray<>();
/**
- * Max number of dynamic + manifest shortcuts that each application can have at a time.
+ * Max number of dynamic + manifest shortcuts that each activity can have at a time.
*/
private int mMaxShortcuts;
/**
+ * Max number of shortcuts that can exists in system ram for each application.
+ */
+ private int mMaxShortcutsPerApp;
+
+ /**
* Max number of updating API calls that each application can make during the interval.
*/
int mMaxUpdatesPerInterval;
@@ -807,6 +820,9 @@
mMaxShortcuts = Math.max(0, (int) parser.getLong(
ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
+ mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
+ ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));
+
final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
? (int) parser.getLong(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1759,6 +1775,13 @@
}
/**
+ * Return the max number of shortcuts can be retaiend in system ram for each application.
+ */
+ int getMaxAppShortcuts() {
+ return mMaxShortcutsPerApp;
+ }
+
+ /**
* - Sends a notification to LauncherApps
* - Write to file
*/
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index 7ce7f7e..810fa5f 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -247,6 +247,9 @@
private static final String MAX_NUM_COMPONENTS_ERR_MSG =
"Total number of components has exceeded the maximum number: " + MAX_NUM_COMPONENTS;
+ /** The maximum permission name length. */
+ private static final int MAX_PERMISSION_NAME_LENGTH = 512;
+
@IntDef(flag = true, prefix = { "PARSE_" }, value = {
PARSE_CHATTY,
PARSE_COLLECT_CERTIFICATES,
@@ -1275,6 +1278,11 @@
// that may change.
String name = sa.getNonResourceString(
R.styleable.AndroidManifestUsesPermission_name);
+ if (TextUtils.length(name) > MAX_PERMISSION_NAME_LENGTH) {
+ return input.error(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+ "The name in the <uses-permission> is greater than "
+ + MAX_PERMISSION_NAME_LENGTH);
+ }
int maxSdkVersion = 0;
TypedValue val = sa.peekValue(
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a2670ee..fd118d2 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3349,8 +3349,8 @@
}
@Override
- public void onKeyguardOccludedChangedLw(boolean occluded) {
- if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
+ public void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition) {
+ if (mKeyguardDelegate != null && waitAppTransition) {
mPendingKeyguardOccluded = occluded;
mKeyguardOccludedChanged = true;
} else {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 4f00992..77007fa 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -166,9 +166,10 @@
/**
* Called when the Keyguard occluded state changed.
+ *
* @param occluded Whether Keyguard is currently occluded or not.
*/
- void onKeyguardOccludedChangedLw(boolean occluded);
+ void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition);
/**
* Applies a keyguard occlusion change if one happened.
diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
index 2d3ede0..7d148f6 100644
--- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
+++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningRegistration.java
@@ -17,6 +17,7 @@
package com.android.server.security.rkp;
import android.os.CancellationSignal;
+import android.os.IBinder;
import android.os.OperationCanceledException;
import android.os.OutcomeReceiver;
import android.security.rkp.IGetKeyCallback;
@@ -39,23 +40,23 @@
*/
final class RemoteProvisioningRegistration extends IRegistration.Stub {
static final String TAG = RemoteProvisioningService.TAG;
- private final ConcurrentHashMap<IGetKeyCallback, CancellationSignal> mGetKeyOperations =
+ private final ConcurrentHashMap<IBinder, CancellationSignal> mGetKeyOperations =
new ConcurrentHashMap<>();
- private final Set<IStoreUpgradedKeyCallback> mStoreUpgradedKeyOperations =
- ConcurrentHashMap.newKeySet();
+ private final Set<IBinder> mStoreUpgradedKeyOperations = ConcurrentHashMap.newKeySet();
private final RegistrationProxy mRegistration;
private final Executor mExecutor;
private class GetKeyReceiver implements OutcomeReceiver<RemotelyProvisionedKey, Exception> {
IGetKeyCallback mCallback;
+
GetKeyReceiver(IGetKeyCallback callback) {
mCallback = callback;
}
@Override
public void onResult(RemotelyProvisionedKey result) {
- mGetKeyOperations.remove(mCallback);
- Log.i(TAG, "Successfully fetched key for client " + mCallback.hashCode());
+ mGetKeyOperations.remove(mCallback.asBinder());
+ Log.i(TAG, "Successfully fetched key for client " + mCallback.asBinder().hashCode());
android.security.rkp.RemotelyProvisionedKey parcelable =
new android.security.rkp.RemotelyProvisionedKey();
parcelable.keyBlob = result.getKeyBlob();
@@ -65,17 +66,21 @@
@Override
public void onError(Exception e) {
- mGetKeyOperations.remove(mCallback);
+ mGetKeyOperations.remove(mCallback.asBinder());
if (e instanceof OperationCanceledException) {
- Log.i(TAG, "Operation cancelled for client " + mCallback.hashCode());
+ Log.i(TAG, "Operation cancelled for client " + mCallback.asBinder().hashCode());
wrapCallback(mCallback::onCancel);
} else if (e instanceof RkpProxyException) {
- Log.e(TAG, "RKP error fetching key for client " + mCallback.hashCode(), e);
+ Log.e(TAG, "RKP error fetching key for client " + mCallback.asBinder().hashCode()
+ + ": "
+ + e.getMessage());
RkpProxyException rkpException = (RkpProxyException) e;
wrapCallback(() -> mCallback.onError(toGetKeyError(rkpException),
e.getMessage()));
} else {
- Log.e(TAG, "Error fetching key for client " + mCallback.hashCode(), e);
+ Log.e(TAG,
+ "Unknown error fetching key for client " + mCallback.asBinder().hashCode()
+ + ": " + e.getMessage());
wrapCallback(() -> mCallback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN,
e.getMessage()));
}
@@ -106,20 +111,23 @@
@Override
public void getKey(int keyId, IGetKeyCallback callback) {
CancellationSignal cancellationSignal = new CancellationSignal();
- if (mGetKeyOperations.putIfAbsent(callback, cancellationSignal) != null) {
- Log.e(TAG, "Client can only request one call at a time " + callback.hashCode());
+ if (mGetKeyOperations.putIfAbsent(callback.asBinder(), cancellationSignal) != null) {
+ Log.e(TAG,
+ "Client can only request one call at a time " + callback.asBinder().hashCode());
throw new IllegalArgumentException(
"Callback is already associated with an existing operation: "
- + callback.hashCode());
+ + callback.asBinder().hashCode());
}
try {
- Log.i(TAG, "Fetching key " + keyId + " for client " + callback.hashCode());
+ Log.i(TAG, "Fetching key " + keyId + " for client " + callback.asBinder().hashCode());
mRegistration.getKeyAsync(keyId, cancellationSignal, mExecutor,
new GetKeyReceiver(callback));
} catch (Exception e) {
- Log.e(TAG, "getKeyAsync threw an exception for client " + callback.hashCode(), e);
- mGetKeyOperations.remove(callback);
+ Log.e(TAG,
+ "getKeyAsync threw an exception for client " + callback.asBinder().hashCode(),
+ e);
+ mGetKeyOperations.remove(callback.asBinder());
wrapCallback(() -> callback.onError(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN,
e.getMessage()));
}
@@ -127,23 +135,23 @@
@Override
public void cancelGetKey(IGetKeyCallback callback) {
- CancellationSignal cancellationSignal = mGetKeyOperations.remove(callback);
+ CancellationSignal cancellationSignal = mGetKeyOperations.remove(callback.asBinder());
if (cancellationSignal == null) {
throw new IllegalArgumentException(
- "Invalid client in cancelGetKey: " + callback.hashCode());
+ "Invalid client in cancelGetKey: " + callback.asBinder().hashCode());
}
- Log.i(TAG, "Requesting cancellation for client " + callback.hashCode());
+ Log.i(TAG, "Requesting cancellation for client " + callback.asBinder().hashCode());
cancellationSignal.cancel();
}
@Override
public void storeUpgradedKeyAsync(byte[] oldKeyBlob, byte[] newKeyBlob,
IStoreUpgradedKeyCallback callback) {
- if (!mStoreUpgradedKeyOperations.add(callback)) {
+ if (!mStoreUpgradedKeyOperations.add(callback.asBinder())) {
throw new IllegalArgumentException(
"Callback is already associated with an existing operation: "
- + callback.hashCode());
+ + callback.asBinder().hashCode());
}
try {
@@ -151,20 +159,20 @@
new OutcomeReceiver<>() {
@Override
public void onResult(Void result) {
- mStoreUpgradedKeyOperations.remove(callback);
+ mStoreUpgradedKeyOperations.remove(callback.asBinder());
wrapCallback(callback::onSuccess);
}
@Override
public void onError(Exception e) {
- mStoreUpgradedKeyOperations.remove(callback);
+ mStoreUpgradedKeyOperations.remove(callback.asBinder());
wrapCallback(() -> callback.onError(e.getMessage()));
}
});
} catch (Exception e) {
Log.e(TAG, "storeUpgradedKeyAsync threw an exception for client "
- + callback.hashCode(), e);
- mStoreUpgradedKeyOperations.remove(callback);
+ + callback.asBinder().hashCode(), e);
+ mStoreUpgradedKeyOperations.remove(callback.asBinder());
wrapCallback(() -> callback.onError(e.getMessage()));
}
}
diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java
index cd1a968..2bd7383 100644
--- a/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java
+++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningService.java
@@ -19,14 +19,18 @@
import android.content.Context;
import android.os.Binder;
import android.os.OutcomeReceiver;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.security.rkp.IGetRegistrationCallback;
import android.security.rkp.IRemoteProvisioning;
import android.security.rkp.service.RegistrationProxy;
import android.util.Log;
+import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.time.Duration;
import java.util.concurrent.Executor;
@@ -57,7 +61,7 @@
try {
mCallback.onSuccess(new RemoteProvisioningRegistration(registration, mExecutor));
} catch (RemoteException e) {
- Log.e(TAG, "Error calling success callback " + mCallback.hashCode(), e);
+ Log.e(TAG, "Error calling success callback " + mCallback.asBinder().hashCode(), e);
}
}
@@ -66,7 +70,7 @@
try {
mCallback.onError(error.toString());
} catch (RemoteException e) {
- Log.e(TAG, "Error calling error callback " + mCallback.hashCode(), e);
+ Log.e(TAG, "Error calling error callback " + mCallback.asBinder().hashCode(), e);
}
}
}
@@ -97,5 +101,18 @@
Binder.restoreCallingIdentity(callingIdentity);
}
}
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
+ new RemoteProvisioningShellCommand().dump(pw);
+ }
+
+ @Override
+ public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
+ ParcelFileDescriptor err, String[] args) {
+ return new RemoteProvisioningShellCommand().exec(this, in.getFileDescriptor(),
+ out.getFileDescriptor(), err.getFileDescriptor(), args);
+ }
}
}
diff --git a/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java b/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java
new file mode 100644
index 0000000..bc39084
--- /dev/null
+++ b/services/core/java/com/android/server/security/rkp/RemoteProvisioningShellCommand.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.security.rkp;
+
+import android.hardware.security.keymint.DeviceInfo;
+import android.hardware.security.keymint.IRemotelyProvisionedComponent;
+import android.hardware.security.keymint.MacedPublicKey;
+import android.hardware.security.keymint.ProtectedData;
+import android.hardware.security.keymint.RpcHardwareInfo;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ShellCommand;
+import android.util.IndentingPrintWriter;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.util.Base64;
+
+import co.nstant.in.cbor.CborDecoder;
+import co.nstant.in.cbor.CborEncoder;
+import co.nstant.in.cbor.CborException;
+import co.nstant.in.cbor.model.Array;
+import co.nstant.in.cbor.model.ByteString;
+import co.nstant.in.cbor.model.DataItem;
+import co.nstant.in.cbor.model.Map;
+import co.nstant.in.cbor.model.SimpleValue;
+import co.nstant.in.cbor.model.UnsignedInteger;
+
+class RemoteProvisioningShellCommand extends ShellCommand {
+ private static final String USAGE = "usage: cmd remote_provisioning SUBCOMMAND [ARGS]\n"
+ + "help\n"
+ + " Show this message.\n"
+ + "dump\n"
+ + " Dump service diagnostics.\n"
+ + "list [--min-version MIN_VERSION]\n"
+ + " List the names of the IRemotelyProvisionedComponent instances.\n"
+ + "csr [--challenge CHALLENGE] NAME\n"
+ + " Generate and print a base64-encoded CSR from the named\n"
+ + " IRemotelyProvisionedComponent. A base64-encoded challenge can be provided,\n"
+ + " or else it defaults to an empty challenge.\n";
+
+ @VisibleForTesting
+ static final String EEK_ED25519_BASE64 = "goRDoQEnoFgqpAEBAycgBiFYIJm57t1e5FL2hcZMYtw+YatXSH11N"
+ + "ymtdoAy0rPLY1jZWEAeIghLpLekyNdOAw7+uK8UTKc7b6XN3Np5xitk/pk5r3bngPpmAIUNB5gqrJFcpyUUS"
+ + "QY0dcqKJ3rZ41pJ6wIDhEOhASegWE6lAQECWCDQrsEVyirPc65rzMvRlh1l6LHd10oaN7lDOpfVmd+YCAM4G"
+ + "CAEIVggvoXnRsSjQlpA2TY6phXQLFh+PdwzAjLS/F4ehyVfcmBYQJvPkOIuS6vRGLEOjl0gJ0uEWP78MpB+c"
+ + "gWDvNeCvvpkeC1UEEvAMb9r6B414vAtzmwvT/L1T6XUg62WovGHWAQ=";
+
+ @VisibleForTesting
+ static final String EEK_P256_BASE64 = "goRDoQEmoFhNpQECAyYgASFYIPcUituX9MxT79JkEcTjdR9mH6RxDGzP"
+ + "+glGgHSHVPKtIlggXn9b9uzk9hnM/xM3/Q+hyJPbGAZ2xF3m12p3hsMtr49YQC+XjkL7vgctlUeFR5NAsB/U"
+ + "m0ekxESp8qEHhxDHn8sR9L+f6Dvg5zRMFfx7w34zBfTRNDztAgRgehXgedOK/ySEQ6EBJqBYcaYBAgJYIDVz"
+ + "tz+gioCJsSZn6ct8daGvAmH8bmUDkTvTS30UlD5GAzgYIAEhWCDgQc8vDzQPHDMsQbDP1wwwVTXSHmpHE0su"
+ + "0UiWfiScaCJYIB/ORcX7YbqBIfnlBZubOQ52hoZHuB4vRfHOr9o/gGjbWECMs7p+ID4ysGjfYNEdffCsOI5R"
+ + "vP9s4Wc7Snm8Vnizmdh8igfY2rW1f3H02GvfMyc0e2XRKuuGmZirOrSAqr1Q";
+
+ private static final int ERROR = -1;
+ private static final int SUCCESS = 0;
+
+ private final Injector mInjector;
+
+ RemoteProvisioningShellCommand() {
+ this(new Injector());
+ }
+
+ @VisibleForTesting
+ RemoteProvisioningShellCommand(Injector injector) {
+ mInjector = injector;
+ }
+
+ @Override
+ public void onHelp() {
+ getOutPrintWriter().print(USAGE);
+ }
+
+ @Override
+ @SuppressWarnings("CatchAndPrintStackTrace")
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+ try {
+ switch (cmd) {
+ case "list":
+ return list();
+ case "csr":
+ return csr();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ } catch (Exception e) {
+ e.printStackTrace(getErrPrintWriter());
+ return ERROR;
+ }
+ }
+
+ @SuppressWarnings("CatchAndPrintStackTrace")
+ void dump(PrintWriter pw) {
+ try {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
+ for (String name : mInjector.getIrpcNames()) {
+ ipw.println(name + ":");
+ ipw.increaseIndent();
+ dumpRpcInstance(ipw, name);
+ ipw.decreaseIndent();
+ }
+ } catch (Exception e) {
+ e.printStackTrace(pw);
+ }
+ }
+
+ private void dumpRpcInstance(PrintWriter pw, String name) throws RemoteException {
+ RpcHardwareInfo info = mInjector.getIrpcBinder(name).getHardwareInfo();
+ pw.println("hwVersion=" + info.versionNumber);
+ pw.println("rpcAuthorName=" + info.rpcAuthorName);
+ if (info.versionNumber < 3) {
+ pw.println("supportedEekCurve=" + info.supportedEekCurve);
+ }
+ pw.println("uniqueId=" + info.uniqueId);
+ if (info.versionNumber >= 3) {
+ pw.println("supportedNumKeysInCsr=" + info.supportedNumKeysInCsr);
+ }
+ }
+
+ private int list() throws RemoteException {
+ for (String name : mInjector.getIrpcNames()) {
+ getOutPrintWriter().println(name);
+ }
+ return SUCCESS;
+ }
+
+ private int csr() throws RemoteException, CborException {
+ byte[] challenge = {};
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "--challenge":
+ challenge = Base64.getDecoder().decode(getNextArgRequired());
+ break;
+ default:
+ getErrPrintWriter().println("error: unknown option " + opt);
+ return ERROR;
+ }
+ }
+ String name = getNextArgRequired();
+
+ IRemotelyProvisionedComponent binder = mInjector.getIrpcBinder(name);
+ RpcHardwareInfo info = binder.getHardwareInfo();
+ MacedPublicKey[] emptyKeys = new MacedPublicKey[] {};
+ byte[] csrBytes;
+ switch (info.versionNumber) {
+ case 1:
+ case 2:
+ DeviceInfo deviceInfo = new DeviceInfo();
+ ProtectedData protectedData = new ProtectedData();
+ byte[] eek = getEekChain(info.supportedEekCurve);
+ byte[] keysToSignMac = binder.generateCertificateRequest(
+ /*testMode=*/false, emptyKeys, eek, challenge, deviceInfo, protectedData);
+ csrBytes = composeCertificateRequestV1(
+ deviceInfo, challenge, protectedData, keysToSignMac);
+ break;
+ case 3:
+ csrBytes = binder.generateCertificateRequestV2(emptyKeys, challenge);
+ break;
+ default:
+ getErrPrintWriter().println("error: unsupported hwVersion: " + info.versionNumber);
+ return ERROR;
+ }
+ getOutPrintWriter().println(Base64.getEncoder().encodeToString(csrBytes));
+ return SUCCESS;
+ }
+
+ private byte[] getEekChain(int supportedEekCurve) {
+ switch (supportedEekCurve) {
+ case RpcHardwareInfo.CURVE_25519:
+ return Base64.getDecoder().decode(EEK_ED25519_BASE64);
+ case RpcHardwareInfo.CURVE_P256:
+ return Base64.getDecoder().decode(EEK_P256_BASE64);
+ default:
+ throw new IllegalArgumentException("unsupported EEK curve: " + supportedEekCurve);
+ }
+ }
+
+ private byte[] composeCertificateRequestV1(DeviceInfo deviceInfo, byte[] challenge,
+ ProtectedData protectedData, byte[] keysToSignMac) throws CborException {
+ Array info = new Array()
+ .add(decode(deviceInfo.deviceInfo))
+ .add(new Map());
+
+ // COSE_Signature with the hmac-sha256 algorithm and without a payload.
+ Array mac = new Array()
+ .add(new ByteString(encode(
+ new Map().put(new UnsignedInteger(1), new UnsignedInteger(5)))))
+ .add(new Map())
+ .add(SimpleValue.NULL)
+ .add(new ByteString(keysToSignMac));
+
+ Array csr = new Array()
+ .add(info)
+ .add(new ByteString(challenge))
+ .add(decode(protectedData.protectedData))
+ .add(mac);
+
+ return encode(csr);
+ }
+
+ private byte[] encode(DataItem item) throws CborException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ new CborEncoder(baos).encode(item);
+ return baos.toByteArray();
+ }
+
+ private DataItem decode(byte[] data) throws CborException {
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ return new CborDecoder(bais).decodeNext();
+ }
+
+ @VisibleForTesting
+ static class Injector {
+ String[] getIrpcNames() {
+ return ServiceManager.getDeclaredInstances(IRemotelyProvisionedComponent.DESCRIPTOR);
+ }
+
+ IRemotelyProvisionedComponent getIrpcBinder(String name) {
+ String irpc = IRemotelyProvisionedComponent.DESCRIPTOR + "/" + name;
+ IRemotelyProvisionedComponent binder =
+ IRemotelyProvisionedComponent.Stub.asInterface(
+ ServiceManager.waitForDeclaredService(irpc));
+ if (binder == null) {
+ throw new IllegalArgumentException("failed to find " + irpc);
+ }
+ return binder;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/OWNERS b/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
index 01b2cb9..1e41886 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
+++ b/services/core/java/com/android/server/soundtrigger_middleware/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
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 b4b8cf9..3d8b293 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -147,7 +147,6 @@
import android.security.metrics.KeystoreAtom;
import android.security.metrics.KeystoreAtomPayload;
import android.security.metrics.RkpErrorStats;
-import android.security.metrics.RkpPoolStats;
import android.security.metrics.StorageStats;
import android.stats.storage.StorageEnums;
import android.telephony.ModemActivityInfo;
@@ -714,7 +713,6 @@
return pullInstalledIncrementalPackagesLocked(atomTag, data);
}
case FrameworkStatsLog.KEYSTORE2_STORAGE_STATS:
- case FrameworkStatsLog.RKP_POOL_STATS:
case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO:
case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO:
case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_PURPOSE_AND_MODES_INFO:
@@ -918,7 +916,6 @@
registerSettingsStats();
registerInstalledIncrementalPackages();
registerKeystoreStorageStats();
- registerRkpPoolStats();
registerKeystoreKeyCreationWithGeneralInfo();
registerKeystoreKeyCreationWithAuthInfo();
registerKeystoreKeyCreationWithPurposeModesInfo();
@@ -4137,14 +4134,6 @@
mStatsCallbackImpl);
}
- private void registerRkpPoolStats() {
- mStatsManager.setPullAtomCallback(
- FrameworkStatsLog.RKP_POOL_STATS,
- null, // use default PullAtomMetadata values,
- DIRECT_EXECUTOR,
- mStatsCallbackImpl);
- }
-
private void registerKeystoreKeyCreationWithGeneralInfo() {
mStatsManager.setPullAtomCallback(
FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO,
@@ -4252,19 +4241,6 @@
return StatsManager.PULL_SUCCESS;
}
- int parseRkpPoolStats(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
- for (KeystoreAtom atomWrapper : atoms) {
- if (atomWrapper.payload.getTag() != KeystoreAtomPayload.rkpPoolStats) {
- return StatsManager.PULL_SKIP;
- }
- RkpPoolStats atom = atomWrapper.payload.getRkpPoolStats();
- pulledData.add(FrameworkStatsLog.buildStatsEvent(
- FrameworkStatsLog.RKP_POOL_STATS, atom.security_level, atom.expiring,
- atom.unassigned, atom.attested, atom.total));
- }
- return StatsManager.PULL_SUCCESS;
- }
-
int parseKeystoreKeyCreationWithGeneralInfo(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
for (KeystoreAtom atomWrapper : atoms) {
if (atomWrapper.payload.getTag()
@@ -4397,8 +4373,6 @@
switch (atomTag) {
case FrameworkStatsLog.KEYSTORE2_STORAGE_STATS:
return parseKeystoreStorageStats(atoms, pulledData);
- case FrameworkStatsLog.RKP_POOL_STATS:
- return parseRkpPoolStats(atoms, pulledData);
case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_GENERAL_INFO:
return parseKeystoreKeyCreationWithGeneralInfo(atoms, pulledData);
case FrameworkStatsLog.KEYSTORE2_KEY_CREATION_WITH_AUTH_INFO:
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
index 2141eba..7f129ea 100644
--- a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -171,6 +171,18 @@
return false;
}
+ for (Map.Entry<Integer, Integer> entry :
+ networkPriority.getCapabilitiesMatchCriteria().entrySet()) {
+ final int cap = entry.getKey();
+ final int matchCriteria = entry.getValue();
+
+ if (matchCriteria == MATCH_REQUIRED && !caps.hasCapability(cap)) {
+ return false;
+ } else if (matchCriteria == MATCH_FORBIDDEN && caps.hasCapability(cap)) {
+ return false;
+ }
+ }
+
if (vcnContext.isInTestMode() && caps.hasTransport(TRANSPORT_TEST)) {
return true;
}
@@ -319,18 +331,6 @@
return false;
}
- for (Map.Entry<Integer, Integer> entry :
- networkPriority.getCapabilitiesMatchCriteria().entrySet()) {
- final int cap = entry.getKey();
- final int matchCriteria = entry.getValue();
-
- if (matchCriteria == MATCH_REQUIRED && !caps.hasCapability(cap)) {
- return false;
- } else if (matchCriteria == MATCH_FORBIDDEN && caps.hasCapability(cap)) {
- return false;
- }
- }
-
return true;
}
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index fd6c974..b160af6a 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -98,7 +98,7 @@
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
}
return mService.getRecentTasks().createRecentTaskInfo(task,
- false /* stripExtras */);
+ false /* stripExtras */, true /* getTasksAllowed */);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 48258a1..1d21b9d 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -403,8 +403,10 @@
return;
}
- mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY));
- if (isKeyguardLocked(displayId)) {
+ final boolean waitAppTransition = isKeyguardLocked(displayId);
+ mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY),
+ waitAppTransition);
+ if (waitAppTransition) {
mService.deferWindowLayout();
try {
mRootWindowContainer.getDefaultDisplay()
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 4860762..1fc061b 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -976,7 +976,7 @@
continue;
}
- res.add(createRecentTaskInfo(task, true /* stripExtras */));
+ res.add(createRecentTaskInfo(task, true /* stripExtras */, getTasksAllowed));
}
return res;
}
@@ -1895,7 +1895,8 @@
/**
* Creates a new RecentTaskInfo from a Task.
*/
- ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras) {
+ ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras,
+ boolean getTasksAllowed) {
final ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
// If the recent Task is detached, we consider it will be re-attached to the default
// TaskDisplayArea because we currently only support recent overview in the default TDA.
@@ -1907,6 +1908,9 @@
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
rti.lastSnapshotData.set(tr.mLastTaskSnapshotData);
+ if (!getTasksAllowed) {
+ Task.trimIneffectiveInfo(tr, rti);
+ }
// Fill in organized child task info for the task created by organizer.
if (tr.mCreatedByOrganizer) {
diff --git a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
index 43baebc..e646f14 100644
--- a/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
+++ b/services/core/java/com/android/server/wm/RemoteDisplayChangeController.java
@@ -114,9 +114,15 @@
// timed-out, so run all continue callbacks and clear the list
synchronized (mService.mGlobalLock) {
for (int i = 0; i < mCallbacks.size(); ++i) {
- mCallbacks.get(i).onContinueRemoteDisplayChange(null /* transaction */);
+ final ContinueRemoteDisplayChangeCallback callback = mCallbacks.get(i);
+ if (i == mCallbacks.size() - 1) {
+ // Clear all callbacks before calling the last one, so that if the callback
+ // itself calls {@link #isWaitingForRemoteDisplayChange()}, it will get
+ // {@code false}. After all, there is nothing pending after this one.
+ mCallbacks.clear();
+ }
+ callback.onContinueRemoteDisplayChange(null /* transaction */);
}
- mCallbacks.clear();
}
}
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 33f019e..4e339f1 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -177,6 +177,10 @@
}
// Fill in some deprecated values
rti.id = rti.taskId;
+
+ if (!mAllowed) {
+ Task.trimIneffectiveInfo(task, rti);
+ }
return rti;
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 25957f1..e0e5ba8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3471,6 +3471,54 @@
info.isSleeping = shouldSleepActivities();
}
+ /**
+ * Removes the activity info if the activity belongs to a different uid, which is
+ * different from the app that hosts the task.
+ */
+ static void trimIneffectiveInfo(Task task, TaskInfo info) {
+ final ActivityRecord baseActivity = task.getActivity(r -> !r.finishing,
+ false /* traverseTopToBottom */);
+ final int baseActivityUid =
+ baseActivity != null ? baseActivity.getUid() : task.effectiveUid;
+
+ if (info.topActivityInfo != null
+ && task.effectiveUid != info.topActivityInfo.applicationInfo.uid) {
+ // Making a copy to prevent eliminating the info in the original ActivityRecord.
+ info.topActivityInfo = new ActivityInfo(info.topActivityInfo);
+ info.topActivityInfo.applicationInfo =
+ new ApplicationInfo(info.topActivityInfo.applicationInfo);
+
+ // Strip the sensitive info.
+ info.topActivity = new ComponentName("", "");
+ info.topActivityInfo.packageName = "";
+ info.topActivityInfo.taskAffinity = "";
+ info.topActivityInfo.processName = "";
+ info.topActivityInfo.name = "";
+ info.topActivityInfo.parentActivityName = "";
+ info.topActivityInfo.targetActivity = "";
+ info.topActivityInfo.splitName = "";
+ info.topActivityInfo.applicationInfo.className = "";
+ info.topActivityInfo.applicationInfo.credentialProtectedDataDir = "";
+ info.topActivityInfo.applicationInfo.dataDir = "";
+ info.topActivityInfo.applicationInfo.deviceProtectedDataDir = "";
+ info.topActivityInfo.applicationInfo.manageSpaceActivityName = "";
+ info.topActivityInfo.applicationInfo.nativeLibraryDir = "";
+ info.topActivityInfo.applicationInfo.nativeLibraryRootDir = "";
+ info.topActivityInfo.applicationInfo.processName = "";
+ info.topActivityInfo.applicationInfo.publicSourceDir = "";
+ info.topActivityInfo.applicationInfo.scanPublicSourceDir = "";
+ info.topActivityInfo.applicationInfo.scanSourceDir = "";
+ info.topActivityInfo.applicationInfo.sourceDir = "";
+ info.topActivityInfo.applicationInfo.taskAffinity = "";
+ info.topActivityInfo.applicationInfo.name = "";
+ info.topActivityInfo.applicationInfo.packageName = "";
+ }
+
+ if (task.effectiveUid != baseActivityUid) {
+ info.baseActivity = new ComponentName("", "");
+ }
+ }
+
@Nullable PictureInPictureParams getPictureInPictureParams() {
final Task topTask = getTopMostTask();
if (topTask == null) return null;
diff --git a/services/core/java/com/android/server/wm/TaskFpsCallbackController.java b/services/core/java/com/android/server/wm/TaskFpsCallbackController.java
index c099628..8c79875 100644
--- a/services/core/java/com/android/server/wm/TaskFpsCallbackController.java
+++ b/services/core/java/com/android/server/wm/TaskFpsCallbackController.java
@@ -26,8 +26,8 @@
final class TaskFpsCallbackController {
private final Context mContext;
- private final HashMap<ITaskFpsCallback, Long> mTaskFpsCallbacks;
- private final HashMap<ITaskFpsCallback, IBinder.DeathRecipient> mDeathRecipients;
+ private final HashMap<IBinder, Long> mTaskFpsCallbacks;
+ private final HashMap<IBinder, IBinder.DeathRecipient> mDeathRecipients;
TaskFpsCallbackController(Context context) {
mContext = context;
@@ -36,32 +36,42 @@
}
void registerListener(int taskId, ITaskFpsCallback callback) {
- if (mTaskFpsCallbacks.containsKey(callback)) {
+ if (callback == null) {
+ return;
+ }
+
+ IBinder binder = callback.asBinder();
+ if (mTaskFpsCallbacks.containsKey(binder)) {
return;
}
final long nativeListener = nativeRegister(callback, taskId);
- mTaskFpsCallbacks.put(callback, nativeListener);
+ mTaskFpsCallbacks.put(binder, nativeListener);
final IBinder.DeathRecipient deathRecipient = () -> unregisterListener(callback);
try {
- callback.asBinder().linkToDeath(deathRecipient, 0);
- mDeathRecipients.put(callback, deathRecipient);
+ binder.linkToDeath(deathRecipient, 0);
+ mDeathRecipients.put(binder, deathRecipient);
} catch (RemoteException e) {
// ignore
}
}
void unregisterListener(ITaskFpsCallback callback) {
- if (!mTaskFpsCallbacks.containsKey(callback)) {
+ if (callback == null) {
return;
}
- callback.asBinder().unlinkToDeath(mDeathRecipients.get(callback), 0);
- mDeathRecipients.remove(callback);
+ IBinder binder = callback.asBinder();
+ if (!mTaskFpsCallbacks.containsKey(binder)) {
+ return;
+ }
- nativeUnregister(mTaskFpsCallbacks.get(callback));
- mTaskFpsCallbacks.remove(callback);
+ binder.unlinkToDeath(mDeathRecipients.get(binder), 0);
+ mDeathRecipients.remove(binder);
+
+ nativeUnregister(mTaskFpsCallbacks.get(binder));
+ mTaskFpsCallbacks.remove(binder);
}
private static native long nativeRegister(ITaskFpsCallback callback, int taskId);
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 2584b86..d9acf41 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -27,3 +27,4 @@
per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS
per-file com_android_server_vibrator_* = file:/services/core/java/com/android/server/vibrator/OWNERS
per-file com_android_server_am_CachedAppOptimizer.cpp = timmurray@google.com, edgararriaga@google.com, dualli@google.com, carmenjackson@google.com, philipcuadra@google.com
+per-file com_android_server_companion_virtual_InputController.cpp = file:/services/companion/java/com/android/server/companion/virtual/OWNERS
diff --git a/services/core/xsd/vts/OWNERS b/services/core/xsd/vts/OWNERS
new file mode 100644
index 0000000..9af2eba
--- /dev/null
+++ b/services/core/xsd/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 151862
+sundongahn@google.com
diff --git a/services/musicrecognition/OWNERS b/services/musicrecognition/OWNERS
index 58f5d40..037b048 100644
--- a/services/musicrecognition/OWNERS
+++ b/services/musicrecognition/OWNERS
@@ -1,6 +1,5 @@
# Bug component: 830636
-joannechung@google.com
oni@google.com
volnov@google.com
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index f05b1d4..8f23ae4 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -20,9 +20,11 @@
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
@@ -53,7 +55,8 @@
public static final String LOG_TAG = "ProfcollectForwardingService";
private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
-
+ private static final String INTENT_UPLOAD_PROFILES =
+ "com.android.server.profcollect.UPLOAD_PROFILES";
private static final long BG_PROCESS_PERIOD = TimeUnit.HOURS.toMillis(4); // every 4 hours.
private IProfCollectd mIProfcollect;
@@ -66,6 +69,16 @@
}
};
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (INTENT_UPLOAD_PROFILES.equals(intent.getAction())) {
+ Log.d(LOG_TAG, "Received broadcast to pack and upload reports");
+ packAndUploadReport();
+ }
+ }
+ };
+
public ProfcollectForwardingService(Context context) {
super(context);
@@ -73,6 +86,10 @@
throw new AssertionError("only one service instance allowed");
}
sSelfService = this;
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(INTENT_UPLOAD_PROFILES);
+ context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
}
/**
@@ -296,7 +313,7 @@
}
if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) {
- packProfileReport();
+ packAndUploadReport();
}
}
@@ -307,7 +324,7 @@
});
}
- private void packProfileReport() {
+ private void packAndUploadReport() {
if (mIProfcollect == null) {
return;
}
diff --git a/services/tests/PackageManagerServiceTests/TEST_MAPPING b/services/tests/PackageManagerServiceTests/TEST_MAPPING
index e98acb2..5d96af9 100644
--- a/services/tests/PackageManagerServiceTests/TEST_MAPPING
+++ b/services/tests/PackageManagerServiceTests/TEST_MAPPING
@@ -55,23 +55,10 @@
// TODO(b/204133664)
"exclude-filter": "com.android.server.pm.test.SdCardEjectionTests"
},
- {
- // TODO(b/272575212)
- "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataBinaryXml"
- },
- {
- "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptDataTextXml"
- },
- {
- "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderBinaryXml"
- },
- {
- "exclude-filter": "com.android.server.pm.test.SettingsTest#testWriteCorruptHeaderTextXml"
- },
- {
+ {
// TODO(b/272714903)
"exclude-filter": "com.android.server.pm.test.OverlayPathsUninstallSystemUpdatesTest#verify"
- }
+ }
]
}
],
diff --git a/services/tests/RemoteProvisioningServiceTests/Android.bp b/services/tests/RemoteProvisioningServiceTests/Android.bp
index 075680a..fc2c085 100644
--- a/services/tests/RemoteProvisioningServiceTests/Android.bp
+++ b/services/tests/RemoteProvisioningServiceTests/Android.bp
@@ -31,6 +31,7 @@
"service-rkp.impl",
"services.core",
"truth-prebuilt",
+ "truth-java8-extension-jar",
],
test_suites: [
"device-tests",
diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
index 1dcd0b9..df7be51 100644
--- a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
+++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningRegistrationTest.java
@@ -23,8 +23,10 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.argThat;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.contains;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
@@ -32,6 +34,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import android.os.Binder;
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
import android.os.OutcomeReceiver;
@@ -101,8 +104,10 @@
.when(mRegistrationProxy).getKeyAsync(eq(42), any(), any(), any());
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
mRegistration.getKey(42, callback);
verify(callback).onSuccess(matches(expectedKey));
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@@ -114,8 +119,10 @@
executor.execute(() -> receiver.onError(expectedException))))
.when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any());
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
mRegistration.getKey(0, callback);
verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN), eq("oops!"));
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@@ -140,18 +147,28 @@
executor.execute(() -> receiver.onError(expectedException))))
.when(mRegistrationProxy).getKeyAsync(eq(0), any(), any(), any());
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
mRegistration.getKey(0, callback);
verify(callback).onError(eq(error), contains(errorField.getName()));
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
}
@Test
public void getKeyCancelDuringProxyOperation() throws Exception {
+ final Binder theBinder = new Binder();
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(theBinder).when(callback).asBinder();
doAnswer(
answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> {
- mRegistration.cancelGetKey(callback);
+ // Use a different callback object to ensure that the callback equivalence
+ // relies on the actual IBinder object.
+ IGetKeyCallback differentCallback = mock(IGetKeyCallback.class);
+ doReturn(theBinder).when(differentCallback).asBinder();
+ mRegistration.cancelGetKey(differentCallback);
+ verify(differentCallback, atLeastOnce()).asBinder();
+ verifyNoMoreInteractions(differentCallback);
assertThat(cancelSignal.isCanceled()).isTrue();
executor.execute(() -> receiver.onError(new OperationCanceledException()));
}))
@@ -159,18 +176,21 @@
mRegistration.getKey(Integer.MAX_VALUE, callback);
verify(callback).onCancel();
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@Test
public void cancelGetKeyWithInvalidCallback() throws Exception {
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback));
}
@Test
public void getKeyRejectsDuplicateCallback() throws Exception {
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
doAnswer(
answerGetKeyAsync((keyId, cancelSignal, executor, receiver) -> {
assertThrows(IllegalArgumentException.class, () ->
@@ -181,12 +201,14 @@
mRegistration.getKey(0, callback);
verify(callback, times(1)).onSuccess(any());
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@Test
public void getKeyCancelAfterCompleteFails() throws Exception {
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
doAnswer(
answerGetKeyAsync((keyId, cancelSignal, executor, receiver) ->
executor.execute(() ->
@@ -197,6 +219,7 @@
mRegistration.getKey(Integer.MIN_VALUE, callback);
verify(callback).onSuccess(any());
assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback));
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@@ -208,10 +231,12 @@
.getKeyAsync(anyInt(), any(), any(), any());
IGetKeyCallback callback = mock(IGetKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
mRegistration.getKey(0, callback);
verify(callback).onError(eq(IGetKeyCallback.ErrorCode.ERROR_UNKNOWN),
eq(expectedException.getMessage()));
assertThrows(IllegalArgumentException.class, () -> mRegistration.cancelGetKey(callback));
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@@ -224,8 +249,10 @@
.storeUpgradedKeyAsync(any(), any(), any(), any());
IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
verify(callback).onSuccess();
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@@ -239,8 +266,10 @@
.storeUpgradedKeyAsync(any(), any(), any(), any());
IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
verify(callback).onError(errorString);
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@@ -252,14 +281,17 @@
.storeUpgradedKeyAsync(any(), any(), any(), any());
IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
verify(callback).onError(errorString);
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
@Test
public void storeUpgradedKeyDuplicateCallback() throws Exception {
IStoreUpgradedKeyCallback callback = mock(IStoreUpgradedKeyCallback.class);
+ doReturn(new Binder()).when(callback).asBinder();
doAnswer(
answerStoreUpgradedKeyAsync((oldBlob, newBlob, executor, receiver) -> {
@@ -273,6 +305,7 @@
mRegistration.storeUpgradedKeyAsync(new byte[0], new byte[0], callback);
verify(callback).onSuccess();
+ verify(callback, atLeastOnce()).asBinder();
verifyNoMoreInteractions(callback);
}
diff --git a/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java
new file mode 100644
index 0000000..2d93120
--- /dev/null
+++ b/services/tests/RemoteProvisioningServiceTests/src/com/android/server/security/rkp/RemoteProvisioningShellCommandTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.security.rkp;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth8.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.security.keymint.DeviceInfo;
+import android.hardware.security.keymint.IRemotelyProvisionedComponent;
+import android.hardware.security.keymint.MacedPublicKey;
+import android.hardware.security.keymint.ProtectedData;
+import android.hardware.security.keymint.RpcHardwareInfo;
+import android.os.Binder;
+import android.os.FileUtils;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Base64;
+import java.util.Map;
+
+@RunWith(AndroidJUnit4.class)
+public class RemoteProvisioningShellCommandTest {
+
+ private static class Injector extends RemoteProvisioningShellCommand.Injector {
+
+ private final Map<String, IRemotelyProvisionedComponent> mIrpcs;
+
+ Injector(Map irpcs) {
+ mIrpcs = irpcs;
+ }
+
+ @Override
+ String[] getIrpcNames() {
+ return mIrpcs.keySet().toArray(new String[0]);
+ }
+
+ @Override
+ IRemotelyProvisionedComponent getIrpcBinder(String name) {
+ IRemotelyProvisionedComponent irpc = mIrpcs.get(name);
+ if (irpc == null) {
+ throw new IllegalArgumentException("failed to find " + irpc);
+ }
+ return irpc;
+ }
+ }
+
+ private static class CommandResult {
+ private int mCode;
+ private String mOut;
+ private String mErr;
+
+ CommandResult(int code, String out, String err) {
+ mCode = code;
+ mOut = out;
+ mErr = err;
+ }
+
+ int getCode() {
+ return mCode;
+ }
+
+ String getOut() {
+ return mOut;
+ }
+
+ String getErr() {
+ return mErr;
+ }
+ }
+
+ private static CommandResult exec(
+ RemoteProvisioningShellCommand cmd, String[] args) throws Exception {
+ File in = File.createTempFile("rpsct_in_", null);
+ File out = File.createTempFile("rpsct_out_", null);
+ File err = File.createTempFile("rpsct_err_", null);
+ int code = cmd.exec(
+ new Binder(),
+ new FileInputStream(in).getFD(),
+ new FileOutputStream(out).getFD(),
+ new FileOutputStream(err).getFD(),
+ args);
+ return new CommandResult(
+ code, FileUtils.readTextFile(out, 0, null), FileUtils.readTextFile(err, 0, null));
+ }
+
+ @Test
+ public void list_zeroInstances() throws Exception {
+ RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand(
+ new Injector(Map.of()));
+ CommandResult res = exec(cmd, new String[] {"list"});
+ assertThat(res.getErr()).isEmpty();
+ assertThat(res.getCode()).isEqualTo(0);
+ assertThat(res.getOut()).isEmpty();
+ assertThat(res.getOut().lines()).isEmpty();
+ }
+
+ @Test
+ public void list_oneInstances() throws Exception {
+ RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand(
+ new Injector(Map.of("default", mock(IRemotelyProvisionedComponent.class))));
+ CommandResult res = exec(cmd, new String[] {"list"});
+ assertThat(res.getErr()).isEmpty();
+ assertThat(res.getCode()).isEqualTo(0);
+ assertThat(res.getOut().lines()).containsExactly("default");
+ }
+
+ @Test
+ public void list_twoInstances() throws Exception {
+ RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand(
+ new Injector(Map.of(
+ "default", mock(IRemotelyProvisionedComponent.class),
+ "strongbox", mock(IRemotelyProvisionedComponent.class))));
+ CommandResult res = exec(cmd, new String[] {"list"});
+ assertThat(res.getErr()).isEmpty();
+ assertThat(res.getCode()).isEqualTo(0);
+ assertThat(res.getOut().lines()).containsExactly("default", "strongbox");
+ }
+
+ @Test
+ public void csr_hwVersion1_withChallenge() throws Exception {
+ IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class);
+ RpcHardwareInfo defaultInfo = new RpcHardwareInfo();
+ defaultInfo.versionNumber = 1;
+ defaultInfo.supportedEekCurve = RpcHardwareInfo.CURVE_25519;
+ when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo);
+ doAnswer(invocation -> {
+ ((DeviceInfo) invocation.getArgument(4)).deviceInfo = new byte[] {0x00};
+ ((ProtectedData) invocation.getArgument(5)).protectedData = new byte[] {0x00};
+ return new byte[] {0x77, 0x77, 0x77, 0x77};
+ }).when(defaultMock).generateCertificateRequest(
+ anyBoolean(), any(), any(), any(), any(), any());
+
+ RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand(
+ new Injector(Map.of("default", defaultMock)));
+ CommandResult res = exec(cmd, new String[] {
+ "csr", "--challenge", "dGVzdHRlc3R0ZXN0dGVzdA==", "default"});
+ verify(defaultMock).generateCertificateRequest(
+ /*test_mode=*/eq(false),
+ eq(new MacedPublicKey[0]),
+ eq(Base64.getDecoder().decode(RemoteProvisioningShellCommand.EEK_ED25519_BASE64)),
+ eq(new byte[] {
+ 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74,
+ 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74}),
+ any(DeviceInfo.class),
+ any(ProtectedData.class));
+ assertThat(res.getErr()).isEmpty();
+ assertThat(res.getCode()).isEqualTo(0);
+ }
+
+ @Test
+ public void csr_hwVersion2_withChallenge() throws Exception {
+ IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class);
+ RpcHardwareInfo defaultInfo = new RpcHardwareInfo();
+ defaultInfo.versionNumber = 2;
+ defaultInfo.supportedEekCurve = RpcHardwareInfo.CURVE_P256;
+ when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo);
+ doAnswer(invocation -> {
+ ((DeviceInfo) invocation.getArgument(4)).deviceInfo = new byte[] {0x00};
+ ((ProtectedData) invocation.getArgument(5)).protectedData = new byte[] {0x00};
+ return new byte[] {0x77, 0x77, 0x77, 0x77};
+ }).when(defaultMock).generateCertificateRequest(
+ anyBoolean(), any(), any(), any(), any(), any());
+
+ RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand(
+ new Injector(Map.of("default", defaultMock)));
+ CommandResult res = exec(cmd, new String[] {
+ "csr", "--challenge", "dGVzdHRlc3R0ZXN0dGVzdA==", "default"});
+ verify(defaultMock).generateCertificateRequest(
+ /*test_mode=*/eq(false),
+ eq(new MacedPublicKey[0]),
+ eq(Base64.getDecoder().decode(RemoteProvisioningShellCommand.EEK_P256_BASE64)),
+ eq(new byte[] {
+ 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74,
+ 0x74, 0x65, 0x73, 0x74, 0x74, 0x65, 0x73, 0x74}),
+ any(DeviceInfo.class),
+ any(ProtectedData.class));
+ assertThat(res.getErr()).isEmpty();
+ assertThat(res.getCode()).isEqualTo(0);
+ }
+
+ @Test
+ public void csr_hwVersion3_withoutChallenge() throws Exception {
+ IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class);
+ RpcHardwareInfo defaultInfo = new RpcHardwareInfo();
+ defaultInfo.versionNumber = 3;
+ when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo);
+ when(defaultMock.generateCertificateRequestV2(any(), any()))
+ .thenReturn(new byte[] {0x68, 0x65, 0x6c, 0x6c, 0x6f});
+
+ RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand(
+ new Injector(Map.of("default", defaultMock)));
+ CommandResult res = exec(cmd, new String[] {"csr", "default"});
+ verify(defaultMock).generateCertificateRequestV2(new MacedPublicKey[0], new byte[0]);
+ assertThat(res.getErr()).isEmpty();
+ assertThat(res.getCode()).isEqualTo(0);
+ assertThat(res.getOut()).isEqualTo("aGVsbG8=\n");
+ }
+
+ @Test
+ public void csr_hwVersion3_withChallenge() throws Exception {
+ IRemotelyProvisionedComponent defaultMock = mock(IRemotelyProvisionedComponent.class);
+ RpcHardwareInfo defaultInfo = new RpcHardwareInfo();
+ defaultInfo.versionNumber = 3;
+ when(defaultMock.getHardwareInfo()).thenReturn(defaultInfo);
+ when(defaultMock.generateCertificateRequestV2(any(), any()))
+ .thenReturn(new byte[] {0x68, 0x69});
+
+ RemoteProvisioningShellCommand cmd = new RemoteProvisioningShellCommand(
+ new Injector(Map.of("default", defaultMock)));
+ CommandResult res = exec(cmd, new String[] {"csr", "--challenge", "dHJpYWw=", "default"});
+ verify(defaultMock).generateCertificateRequestV2(
+ new MacedPublicKey[0], new byte[] {0x74, 0x72, 0x69, 0x61, 0x6c});
+ assertThat(res.getErr()).isEmpty();
+ assertThat(res.getCode()).isEqualTo(0);
+ assertThat(res.getOut()).isEqualTo("aGk=\n");
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/OWNERS b/services/tests/mockingservicestests/src/com/android/server/rollback/OWNERS
new file mode 100644
index 0000000..daa0211
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/OWNERS
@@ -0,0 +1,3 @@
+ancr@google.com
+harshitmahajan@google.com
+robertogil@google.com
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index d622a80..40d9948 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -103,6 +103,9 @@
data: [
":JobTestApp",
":StubTestApp",
+ ":SimpleServiceTestApp1",
+ ":SimpleServiceTestApp2",
+ ":SimpleServiceTestApp3",
],
java_resources: [
diff --git a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
index dea31d7..3ad24de 100644
--- a/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/SpatializerHelperTest.java
@@ -17,12 +17,17 @@
import com.android.server.audio.SpatializerHelper.SADeviceState;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
import android.media.AudioSystem;
import android.util.Log;
@@ -36,6 +41,7 @@
import org.mockito.Mock;
import org.mockito.Spy;
+import java.util.ArrayList;
import java.util.List;
@MediumTest
@@ -49,16 +55,35 @@
@Mock private AudioService mMockAudioService;
@Spy private AudioSystemAdapter mSpyAudioSystem;
+ @Mock private AudioSystemAdapter mMockAudioSystem;
@Before
public void setUp() throws Exception {
mMockAudioService = mock(AudioService.class);
- mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
+ }
- mSpatHelper = new SpatializerHelper(mMockAudioService, mSpyAudioSystem,
+ /**
+ * Initializes mSpatHelper, the SpatizerHelper instance under test, to use the mock or spy
+ * AudioSystemAdapter
+ * @param useSpyAudioSystem true to use the spy adapter, mSpyAudioSystem, or false to use
+ * the mock adapter, mMockAudioSystem.
+ */
+ private void setUpSpatHelper(boolean useSpyAudioSystem) {
+ final AudioSystemAdapter asAdapter;
+ if (useSpyAudioSystem) {
+ mSpyAudioSystem = spy(new NoOpAudioSystemAdapter());
+ asAdapter = mSpyAudioSystem;
+ mMockAudioSystem = null;
+ } else {
+ mSpyAudioSystem = null;
+ mMockAudioSystem = mock(NoOpAudioSystemAdapter.class);
+ asAdapter = mMockAudioSystem;
+ }
+ mSpatHelper = new SpatializerHelper(mMockAudioService, asAdapter,
true /*binauralEnabledDefault*/,
true /*transauralEnabledDefault*/,
false /*headTrackingEnabledDefault*/);
+
}
/**
@@ -68,6 +93,7 @@
*/
@Test
public void testSADeviceStateNullAddressCtor() throws Exception {
+ setUpSpatHelper(true /*useSpyAudioSystem*/);
try {
SADeviceState devState = new SADeviceState(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, null);
devState = new SADeviceState(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, null);
@@ -78,6 +104,7 @@
@Test
public void testSADeviceStateStringSerialization() throws Exception {
Log.i(TAG, "starting testSADeviceStateStringSerialization");
+ setUpSpatHelper(true /*useSpyAudioSystem*/);
final SADeviceState devState = new SADeviceState(
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "bla");
devState.mHasHeadTracker = false;
@@ -93,6 +120,7 @@
@Test
public void testSADeviceSettings() throws Exception {
Log.i(TAG, "starting testSADeviceSettings");
+ setUpSpatHelper(true /*useSpyAudioSystem*/);
final AudioDeviceAttributes dev1 =
new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
final AudioDeviceAttributes dev2 =
@@ -143,4 +171,34 @@
Log.i(TAG, "device settingsRestored: " + settingsRestored);
Assert.assertEquals(settings, settingsRestored);
}
+
+ /**
+ * Test that null devices for routing do not break canBeSpatialized
+ * @throws Exception
+ */
+ @Test
+ public void testNoRoutingCanBeSpatialized() throws Exception {
+ Log.i(TAG, "Starting testNoRoutingCanBeSpatialized");
+ setUpSpatHelper(false /*useSpyAudioSystem*/);
+ mSpatHelper.forceStateForTest(SpatializerHelper.STATE_ENABLED_AVAILABLE);
+
+ final ArrayList<AudioDeviceAttributes> emptyList = new ArrayList<>(0);
+ final ArrayList<AudioDeviceAttributes> listWithNull = new ArrayList<>(1);
+ listWithNull.add(null);
+ final AudioAttributes media = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA).build();
+ final AudioFormat spatialFormat = new AudioFormat.Builder()
+ .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
+ .setChannelMask(AudioFormat.CHANNEL_OUT_5POINT1).build();
+
+ when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+ .thenReturn(emptyList);
+ Assert.assertFalse("can be spatialized on empty routing",
+ mSpatHelper.canBeSpatialized(media, spatialFormat));
+
+ when(mMockAudioSystem.getDevicesForAttributes(any(AudioAttributes.class), anyBoolean()))
+ .thenReturn(listWithNull);
+ Assert.assertFalse("can be spatialized on null routing",
+ mSpatHelper.canBeSpatialized(media, spatialFormat));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 035249e..a4a35dc 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -344,6 +344,7 @@
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_succeedsWithCertFile() throws Exception {
int uid = Binder.getCallingUid();
@@ -365,6 +366,7 @@
assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_updatesShouldCreatesnapshotOnCertUpdate() throws Exception {
int uid = Binder.getCallingUid();
@@ -392,6 +394,7 @@
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue();
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_triesToFilterRootAlias() throws Exception {
int uid = Binder.getCallingUid();
@@ -413,6 +416,7 @@
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_usesProdCertificateForEmptyRootAlias() throws Exception {
int uid = Binder.getCallingUid();
@@ -433,6 +437,7 @@
assertThat(activeRootAlias).isEqualTo(DEFAULT_ROOT_CERT_ALIAS);
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_usesProdCertificateForNullRootAlias() throws Exception {
int uid = Binder.getCallingUid();
@@ -453,6 +458,7 @@
assertThat(activeRootAlias).isEqualTo(DEFAULT_ROOT_CERT_ALIAS);
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_regeneratesCounterId() throws Exception {
int uid = Binder.getCallingUid();
@@ -483,6 +489,7 @@
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_updatesWithLargerSerial() throws Exception {
int uid = Binder.getCallingUid();
@@ -500,6 +507,7 @@
assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isFalse();
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_throwsExceptionOnSmallerSerial() throws Exception {
int uid = Binder.getCallingUid();
@@ -565,6 +573,7 @@
TestData.getInsecureCertPathForEndpoint1());
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryService_ignoresTheSameSerial() throws Exception {
int uid = Binder.getCallingUid();
@@ -615,6 +624,7 @@
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryServiceWithSigFile_succeeds() throws Exception {
int uid = Binder.getCallingUid();
@@ -630,6 +640,7 @@
assertThat(mRecoverableKeyStoreDb.getRecoveryServicePublicKey(userId, uid)).isNull();
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void initRecoveryServiceWithSigFile_usesProdCertificateForNullRootAlias()
throws Exception {
@@ -723,6 +734,7 @@
eq(Manifest.permission.RECOVER_KEYSTORE), any());
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void startRecoverySessionWithCertPath_storesTheSessionInfo() throws Exception {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
@@ -740,6 +752,7 @@
assertEquals(KEY_CLAIMANT_LENGTH_BYTES, entry.getKeyClaimant().length);
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void startRecoverySessionWithCertPath_checksPermissionFirst() throws Exception {
mRecoverableKeyStoreManager.startRecoverySessionWithCertPath(
@@ -809,6 +822,7 @@
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void startRecoverySession_throwsIfBadNumberOfSecrets() throws Exception {
try {
@@ -825,6 +839,7 @@
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void startRecoverySession_throwsIfPublicKeysMismatch() throws Exception {
byte[] vaultParams = TEST_VAULT_PARAMS.clone();
@@ -843,6 +858,7 @@
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void startRecoverySessionWithCertPath_throwsIfBadNumberOfSecrets() throws Exception {
try {
@@ -860,6 +876,7 @@
}
}
+ @Ignore("Causing breakages so ignoring to resolve, b/281583079")
@Test
public void startRecoverySessionWithCertPath_throwsIfPublicKeysMismatch() throws Exception {
byte[] vaultParams = TEST_VAULT_PARAMS.clone();
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 7c7e2ee..012596e 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -151,6 +151,7 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.MediumTest;
import android.text.TextUtils;
@@ -241,6 +242,7 @@
private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey";
private static final String TEST_IMSI = "310210";
private static final int TEST_SUB_ID = 42;
+ private static final int TEST_SUB_ID2 = 24;
private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS);
private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI)
@@ -282,6 +284,8 @@
private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ private TelephonyCallback.ActiveDataSubscriptionIdListener mActiveDataSubIdListener;
+
private ActivityManagerInternal mActivityManagerInternal;
private PackageManagerInternal mPackageManagerInternal;
@@ -357,6 +361,8 @@
private class TestDependencies extends NetworkPolicyManagerService.Dependencies {
private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>();
+ private int mMockDefaultDataSubId;
+ private int mMockedActiveDataSubId;
TestDependencies(Context context) {
super(context);
@@ -394,6 +400,21 @@
final NetworkStats.Bucket bucket = mMockedStats.get(uid);
setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes);
}
+
+ void setDefaultAndActiveDataSubId(int defaultDataSubId, int activeDataSubId) {
+ mMockDefaultDataSubId = defaultDataSubId;
+ mMockedActiveDataSubId = activeDataSubId;
+ }
+
+ @Override
+ int getDefaultDataSubId() {
+ return mMockDefaultDataSubId;
+ }
+
+ @Override
+ int getActivateDataSubId() {
+ return mMockedActiveDataSubId;
+ }
}
@Before
@@ -551,6 +572,14 @@
NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, "");
mDefaultWarningBytes = defaultPolicy.warningBytes;
mDefaultLimitBytes = defaultPolicy.limitBytes;
+
+ // Catch TelephonyCallback during systemReady().
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackArgumentCaptor =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+ verify(mTelephonyManager).registerTelephonyCallback(any(),
+ telephonyCallbackArgumentCaptor.capture());
+ mActiveDataSubIdListener = (TelephonyCallback.ActiveDataSubscriptionIdListener)
+ telephonyCallbackArgumentCaptor.getValue();
}
@After
@@ -1243,6 +1272,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1258,6 +1288,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1275,6 +1306,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
expectDefaultCarrierConfig();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1291,6 +1323,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.updateNetworks();
@@ -1304,6 +1337,7 @@
{
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
+ clearInvocations(mNotifManager);
mService.snoozeLimit(sTemplateCarrierMetered);
mService.updateNetworks();
@@ -1314,6 +1348,31 @@
verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
isA(Notification.class), eq(UserHandle.ALL));
}
+ // The sub is no longer used for data(e.g. user uses another sub), hide the notifications.
+ {
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+ notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID2);
+ verify(mNotifManager, atLeastOnce()).cancel(any(), eq(TYPE_LIMIT_SNOOZED));
+ }
+ // The sub is not active for data(e.g. due to auto data switch), but still default for data,
+ // show notification.
+ {
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+ notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID, TEST_SUB_ID2);
+ verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+ isA(Notification.class), eq(UserHandle.ALL));
+ }
+ // The sub is active for data, but not the default(e.g. due to auto data switch),
+ // show notification.
+ {
+ reset(mTelephonyManager, mNetworkManager, mNotifManager);
+
+ notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID);
+ verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED),
+ isA(Notification.class), eq(UserHandle.ALL));
+ }
}
@Test
@@ -2377,6 +2436,7 @@
String subscriberId) {
when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(
createSubscriptionInfoList(subscriptionId));
+ notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId);
TelephonyManager subTelephonyManager;
subTelephonyManager = mock(TelephonyManager.class);
@@ -2388,6 +2448,16 @@
}
/**
+ * Telephony Manager callback notifies data sub Id changes.
+ * @param defaultDataSubId The mock default data sub Id.
+ * @param activeDataSubId The mock active data sub Id.
+ */
+ private void notifyDefaultAndActiveDataSubIdChange(int defaultDataSubId, int activeDataSubId) {
+ mDeps.setDefaultAndActiveDataSubId(defaultDataSubId, activeDataSubId);
+ mActiveDataSubIdListener.onActiveDataSubscriptionIdChanged(activeDataSubId);
+ }
+
+ /**
* Creates mock {@link SubscriptionInfo} from subscription id.
*/
private List<SubscriptionInfo> createSubscriptionInfoList(int subId) {
diff --git a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
index 33385af..1e41886 100644
--- a/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/soundtrigger_middleware/OWNERS
@@ -1 +1 @@
-include /media/aidl/android/media/soundtrigger_middleware/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/services/tests/servicestests/utils/com/android/server/testutils/OWNERS b/services/tests/servicestests/utils/com/android/server/testutils/OWNERS
new file mode 100644
index 0000000..bdacf7f
--- /dev/null
+++ b/services/tests/servicestests/utils/com/android/server/testutils/OWNERS
@@ -0,0 +1 @@
+per-file *Transaction.java = file:/services/core/java/com/android/server/wm/OWNERS
\ No newline at end of file
diff --git a/services/tests/uiservicestests/OWNERS b/services/tests/uiservicestests/OWNERS
new file mode 100644
index 0000000..c0cbea9
--- /dev/null
+++ b/services/tests/uiservicestests/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/notification/OWNERS
\ No newline at end of file
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index adf694c..db6ac0b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -30,6 +30,7 @@
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.os.Process.NOBODY_UID;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -1220,20 +1221,35 @@
@Test
public void testCreateRecentTaskInfo_detachedTask() {
- final Task task = createTaskBuilder(".Task").setCreateActivity(true).build();
+ final Task task = createTaskBuilder(".Task").build();
+ final ComponentName componentName = getUniqueComponentName();
+ new ActivityBuilder(mSupervisor.mService)
+ .setTask(task)
+ .setUid(NOBODY_UID)
+ .setComponent(componentName)
+ .build();
final TaskDisplayArea tda = task.getDisplayArea();
assertTrue(task.isAttached());
assertTrue(task.supportsMultiWindow());
- RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true);
+ RecentTaskInfo info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */,
+ true /* getTasksAllowed */);
assertTrue(info.supportsMultiWindow);
+ info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */,
+ false /* getTasksAllowed */);
+
+ assertFalse(info.topActivity.equals(componentName));
+ assertFalse(info.topActivityInfo.packageName.equals(componentName.getPackageName()));
+ assertFalse(info.baseActivity.equals(componentName));
+
// The task can be put in split screen even if it is not attached now.
task.removeImmediately();
- info = mRecentTasks.createRecentTaskInfo(task, true);
+ info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */,
+ true /* getTasksAllowed */);
assertTrue(info.supportsMultiWindow);
@@ -1242,7 +1258,8 @@
doReturn(false).when(tda).supportsNonResizableMultiWindow();
doReturn(false).when(task).isResizeable();
- info = mRecentTasks.createRecentTaskInfo(task, true);
+ info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */,
+ true /* getTasksAllowed */);
assertFalse(info.supportsMultiWindow);
@@ -1250,7 +1267,8 @@
// the device supports it.
doReturn(true).when(tda).supportsNonResizableMultiWindow();
- info = mRecentTasks.createRecentTaskInfo(task, true);
+ info = mRecentTasks.createRecentTaskInfo(task, true /* stripExtras */,
+ true /* getTasksAllowed */);
assertTrue(info.supportsMultiWindow);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index d2cb7ba..e2db2e6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -222,7 +222,7 @@
}
@Override
- public void onKeyguardOccludedChangedLw(boolean occluded) {
+ public void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition) {
}
public void setSafeMode(boolean safeMode) {
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 42a5af7..3a8ef33 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -71,6 +71,7 @@
private static final int USB_VENDORID_SONY = 0x054C;
private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT1 = 0x05C4;
private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT2 = 0x09CC;
+ private static final int USB_PRODUCTID_PS5CONTROLLER = 0x0CE6;
private static final int USB_DENYLIST_OUTPUT = 0x0001;
private static final int USB_DENYLIST_INPUT = 0x0002;
@@ -93,6 +94,9 @@
USB_DENYLIST_OUTPUT),
new DenyListEntry(USB_VENDORID_SONY,
USB_PRODUCTID_PS4CONTROLLER_ZCT2,
+ USB_DENYLIST_OUTPUT),
+ new DenyListEntry(USB_VENDORID_SONY,
+ USB_PRODUCTID_PS5CONTROLLER,
USB_DENYLIST_OUTPUT));
private static boolean isDeviceDenylisted(int vendorId, int productId, int flags) {
diff --git a/services/voiceinteraction/OWNERS b/services/voiceinteraction/OWNERS
index ef1061b..40e8d26 100644
--- a/services/voiceinteraction/OWNERS
+++ b/services/voiceinteraction/OWNERS
@@ -1 +1,2 @@
include /core/java/android/service/voice/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
index 01b2cb9..1e41886 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
@@ -1,2 +1 @@
-atneya@google.com
-elaurent@google.com
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index ec18c6a..7a53447 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -555,6 +555,11 @@
/**
* Sets the address. See {@link PhoneAccount#getAddress}.
+ * <p>
+ * Note: The entire URI value is limited to 256 characters. This check is
+ * enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)} and will cause an
+ * {@link IllegalArgumentException} to be thrown if URI is over 256.
*
* @param value The address of the phone account.
* @return The builder.
@@ -588,6 +593,10 @@
/**
* Sets the icon. See {@link PhoneAccount#getIcon}.
+ * <p>
+ * Note: An {@link IllegalArgumentException} if the Icon cannot be written to memory.
+ * This check is enforced when registering the PhoneAccount via
+ * {@link TelecomManager#registerPhoneAccount(PhoneAccount)}
*
* @param icon The icon to set.
*/
@@ -621,6 +630,10 @@
/**
* Specifies an additional URI scheme supported by the {@link PhoneAccount}.
*
+ * <p>
+ * Each URI scheme is limited to 256 characters. Adding a scheme over 256 characters will
+ * cause an {@link IllegalArgumentException} to be thrown when the account is registered.
+ *
* @param uriScheme The URI scheme.
* @return The builder.
*/
@@ -634,6 +647,12 @@
/**
* Specifies the URI schemes supported by the {@link PhoneAccount}.
*
+ * <p>
+ * A max of 10 URI schemes can be added per account. Additionally, each URI scheme is
+ * limited to 256 characters. Adding more than 10 URI schemes or 256 characters on any
+ * scheme will cause an {@link IllegalArgumentException} to be thrown when the account
+ * is registered.
+ *
* @param uriSchemes The URI schemes.
* @return The builder.
*/
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f570f87..c90b94d 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3708,13 +3708,12 @@
* NR_SA - NR SA is unmetered for sub-6 frequencies
* NR_SA_MMWAVE - NR SA is unmetered for mmwave frequencies
*
- * Note that this config only applies if an unmetered SubscriptionPlan is set via
- * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set
+ * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link
+ * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set
* via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)}
* or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}.
* If neither SubscriptionPlans nor an override are set, then no network types can be unmetered
* regardless of the value of this config.
- * TODO: remove other unmetered keys and replace with this
* @hide
*/
public static final String KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY =
@@ -3729,73 +3728,18 @@
* NR_SA - NR SA is unmetered when roaming for sub-6 frequencies
* NR_SA_MMWAVE - NR SA is unmetered when roaming for mmwave frequencies
*
- * Note that this config only applies if an unmetered SubscriptionPlan is set via
- * {@link SubscriptionManager#setSubscriptionPlans(int, List)} or an unmetered override is set
+ * Note that this config only applies if an unmetered SubscriptionPlan is set via {@link
+ * SubscriptionManager#setSubscriptionPlans(int, List, long)} or an unmetered override is set
* via {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, int[], long)}
* or {@link SubscriptionManager#setSubscriptionOverrideUnmetered(int, boolean, long)}.
* If neither SubscriptionPlans nor an override are set, then no network types can be unmetered
* when roaming regardless of the value of this config.
- * TODO: remove KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL and replace with this
* @hide
*/
public static final String KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY =
"roaming_unmetered_network_types_string_array";
/**
- * Whether NR (non-standalone) should be unmetered for all frequencies.
- * If either {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL} or
- * {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL} are true, then this value will be ignored.
- * @hide
- */
- public static final String KEY_UNMETERED_NR_NSA_BOOL = "unmetered_nr_nsa_bool";
-
- /**
- * Whether NR (non-standalone) frequencies above 6GHz (millimeter wave) should be unmetered.
- * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
- * @hide
- */
- public static final String KEY_UNMETERED_NR_NSA_MMWAVE_BOOL = "unmetered_nr_nsa_mmwave_bool";
-
- /**
- * Whether NR (non-standalone) frequencies below 6GHz (sub6) should be unmetered.
- * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
- * @hide
- */
- public static final String KEY_UNMETERED_NR_NSA_SUB6_BOOL = "unmetered_nr_nsa_sub6_bool";
-
- /**
- * Whether NR (non-standalone) should be unmetered when the device is roaming.
- * If false, then the values for {@link #KEY_UNMETERED_NR_NSA_BOOL},
- * {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL}, {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL},
- * and unmetered {@link SubscriptionPlan} will be ignored.
- * @hide
- */
- public static final String KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL =
- "unmetered_nr_nsa_when_roaming_bool";
-
- /**
- * Whether NR (standalone) should be unmetered for all frequencies.
- * If either {@link #KEY_UNMETERED_NR_SA_MMWAVE_BOOL} or
- * {@link #KEY_UNMETERED_NR_SA_SUB6_BOOL} are true, then this value will be ignored.
- * @hide
- */
- public static final String KEY_UNMETERED_NR_SA_BOOL = "unmetered_nr_sa_bool";
-
- /**
- * Whether NR (standalone) frequencies above 6GHz (millimeter wave) should be unmetered.
- * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored.
- * @hide
- */
- public static final String KEY_UNMETERED_NR_SA_MMWAVE_BOOL = "unmetered_nr_sa_mmwave_bool";
-
- /**
- * Whether NR (standalone) frequencies below 6GHz (sub6) should be unmetered.
- * If this is true, then the value for {@link #KEY_UNMETERED_NR_SA_BOOL} will be ignored.
- * @hide
- */
- public static final String KEY_UNMETERED_NR_SA_SUB6_BOOL = "unmetered_nr_sa_sub6_bool";
-
- /**
* Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable
* this feature.
* @hide
@@ -4478,6 +4422,57 @@
"data_stall_recovery_should_skip_bool_array";
/**
+ * String array containing the list of names for service numbers provided by carriers. This key
+ * should be used with {@link #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY}. The names provided in
+ * this array will be mapped 1:1 with the numbers provided in the {@link
+ * #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY} array.
+ *
+ * <p>The data would be considered valid if and only if:
+ *
+ * <ul>
+ * <li>The number of items in both the arrays are equal
+ * <li>The data added to the {@link #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY} array is valid.
+ * See {@link #KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY} for more information.
+ * </ul>
+ *
+ * <p>Example:
+ *
+ * <pre><code>
+ * <string-array name="carrier_service_name_array" num="2">
+ * <item value="Police"/>
+ * <item value="Ambulance"/>
+ * </string-array>
+ * </code></pre>
+ */
+ public static final String KEY_CARRIER_SERVICE_NAME_STRING_ARRAY = "carrier_service_name_array";
+
+ /**
+ * String array containing the list of service numbers provided by carriers. This key should be
+ * used with {@link #KEY_CARRIER_SERVICE_NAME_STRING_ARRAY}. The numbers provided in this array
+ * will be mapped 1:1 with the names provided in the {@link
+ * #KEY_CARRIER_SERVICE_NAME_STRING_ARRAY} array.
+ *
+ * <p>The data would be considered valid if and only if:
+ *
+ * <ul>
+ * <li>The number of items in both the arrays are equal
+ * <li>The item added in this key follows a specific format. Either it should be all numbers,
+ * or "+" followed by all numbers.
+ * </ul>
+ *
+ * <p>Example:
+ *
+ * <pre><code>
+ * <string-array name="carrier_service_number_array" num="2">
+ * <item value="123"/>
+ * <item value="+343"/>
+ * </string-array>
+ * </code></pre>
+ */
+ public static final String KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY =
+ "carrier_service_number_array";
+
+ /**
* Configs used by ImsServiceEntitlement.
*/
public static final class ImsServiceEntitlement {
@@ -4833,11 +4828,32 @@
* The max acceptable value of this config is 24 hours.
*
* @hide
+ * @deprecated Use {@link #KEY_DATA_SWITCH_VALIDATION_MIN_INTERVAL_MILLIS_LONG} instead.
*/
+ @Deprecated
public static final String KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG =
"data_switch_validation_min_gap_long";
/**
+ * Data switch validation minimal interval, in milliseconds.
+ *
+ * If a connection to the default (Internet) PDN for the current subscription is validated on
+ * a given operator within a given tracking area, re-validations to that matching operator will
+ * be skipped if they would occur within the specified interval. Instead, the connection will
+ * automatically considered validated.
+ *
+ * If the network was validated within the interval but the latest validation result was false,
+ * the validation will not be skipped. If not set or set to 0, validation will not be skipped.
+ *
+ * The valid range of value is between 0 millisecond and 24 hours, inclusive in both sides. The
+ * default value is 24 hours.
+ *
+ * @see android.net.NetworkCapabilities#NET_CAPABILITY_VALIDATED
+ */
+ public static final String KEY_DATA_SWITCH_VALIDATION_MIN_INTERVAL_MILLIS_LONG =
+ KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG;
+
+ /**
* A boolean property indicating whether this subscription should be managed as an opportunistic
* subscription.
*
@@ -9183,13 +9199,6 @@
sDefaults.putStringArray(KEY_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[] {
"NR_NSA", "NR_NSA_MMWAVE", "NR_SA", "NR_SA_MMWAVE"});
sDefaults.putStringArray(KEY_ROAMING_UNMETERED_NETWORK_TYPES_STRING_ARRAY, new String[0]);
- sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
- sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
- sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false);
- sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL, false);
- sDefaults.putBoolean(KEY_UNMETERED_NR_SA_BOOL, false);
- sDefaults.putBoolean(KEY_UNMETERED_NR_SA_MMWAVE_BOOL, false);
- sDefaults.putBoolean(KEY_UNMETERED_NR_SA_SUB6_BOOL, false);
sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_WIFI_CALLING_ICON_IN_STATUS_BAR_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL, false);
@@ -9284,7 +9293,8 @@
sDefaults.putInt(KEY_GBA_UA_TLS_CIPHER_SUITE_INT, TlsParams.TLS_NULL_WITH_NULL_NULL);
sDefaults.putBoolean(KEY_SHOW_FORWARDED_NUMBER_BOOL, false);
- sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG, TimeUnit.DAYS.toMillis(1));
+ sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_MIN_INTERVAL_MILLIS_LONG,
+ TimeUnit.DAYS.toMillis(1));
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY,
new String[0]);
sDefaults.putStringArray(KEY_APN_PRIORITY_STRING_ARRAY, new String[] {
@@ -9350,6 +9360,8 @@
new long[] {180000, 180000, 180000, 180000});
sDefaults.putBooleanArray(KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY,
new boolean[] {false, false, true, false, false});
+ sDefaults.putStringArray(KEY_CARRIER_SERVICE_NAME_STRING_ARRAY, new String[0]);
+ sDefaults.putStringArray(KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY, new String[0]);
}
/**
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index a0467c2..f1f13bc 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -184,10 +184,11 @@
private final int mTransportType;
/**
- * The initial registration state
+ * The true registration state of network, This is not affected by any carrier config or
+ * resource overlay.
*/
@RegistrationState
- private final int mInitialRegistrationState;
+ private final int mNetworkRegistrationState;
/**
* The registration state that might have been overridden by config
@@ -264,7 +265,7 @@
mDomain = domain;
mTransportType = transportType;
mRegistrationState = registrationState;
- mInitialRegistrationState = registrationState;
+ mNetworkRegistrationState = registrationState;
mRoamingType = (registrationState == REGISTRATION_STATE_ROAMING)
? ServiceState.ROAMING_TYPE_UNKNOWN : ServiceState.ROAMING_TYPE_NOT_ROAMING;
setAccessNetworkTechnology(accessNetworkTechnology);
@@ -320,7 +321,7 @@
mDomain = source.readInt();
mTransportType = source.readInt();
mRegistrationState = source.readInt();
- mInitialRegistrationState = source.readInt();
+ mNetworkRegistrationState = source.readInt();
mRoamingType = source.readInt();
mAccessNetworkTechnology = source.readInt();
mRejectCause = source.readInt();
@@ -347,7 +348,7 @@
mDomain = nri.mDomain;
mTransportType = nri.mTransportType;
mRegistrationState = nri.mRegistrationState;
- mInitialRegistrationState = nri.mInitialRegistrationState;
+ mNetworkRegistrationState = nri.mNetworkRegistrationState;
mRoamingType = nri.mRoamingType;
mAccessNetworkTechnology = nri.mAccessNetworkTechnology;
mIsUsingCarrierAggregation = nri.mIsUsingCarrierAggregation;
@@ -400,40 +401,72 @@
}
/**
- * @return The registration state.
+ * @return The registration state. Note this value can be affected by the carrier config
+ * override.
*
+ * @deprecated Use {@link #getNetworkRegistrationState}, which is not affected by any carrier
+ * config or resource overlay, instead.
* @hide
*/
+ @Deprecated
@SystemApi
public @RegistrationState int getRegistrationState() {
return mRegistrationState;
}
/**
- * @return The initial registration state.
+ * @return The true registration state of network. (This value is not affected by any carrier
+ * config or resource overlay override).
*
* @hide
*/
- public @RegistrationState int getInitialRegistrationState() {
- return mInitialRegistrationState;
+ @SystemApi
+ public @RegistrationState int getNetworkRegistrationState() {
+ return mNetworkRegistrationState;
}
/**
- * @return {@code true} if registered on roaming or home network, {@code false} otherwise.
+ * @return {@code true} if registered on roaming or home network. Note this value can be
+ * affected by the carrier config override.
+ *
+ * @deprecated Use {@link #isNetworkRegistered}, which is not affected by any carrier config or
+ * resource overlay, instead.
*/
+ @Deprecated
public boolean isRegistered() {
return mRegistrationState == REGISTRATION_STATE_HOME
|| mRegistrationState == REGISTRATION_STATE_ROAMING;
}
/**
- * @return {@code true} if searching for service, {@code false} otherwise.
+ * @return {@code true} if registered on roaming or home network, {@code false} otherwise. (This
+ * value is not affected by any carrier config or resource overlay override).
*/
+ public boolean isNetworkRegistered() {
+ return mNetworkRegistrationState == REGISTRATION_STATE_HOME
+ || mNetworkRegistrationState == REGISTRATION_STATE_ROAMING;
+ }
+
+ /**
+ * @return {@code true} if searching for service, {@code false} otherwise.
+ *
+ * @deprecated Use {@link #isNetworkRegistered}, which is not affected by any carrier config or
+ * resource overlay, instead.
+ */
+ @Deprecated
public boolean isSearching() {
return mRegistrationState == REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
}
/**
+ * @return {@code true} if searching for service, {@code false} otherwise. (This value is not
+ * affected by any carrier config or resource overlay override).
+ */
+ public boolean isNetworkSearching() {
+ return mNetworkRegistrationState == REGISTRATION_STATE_NOT_REGISTERED_SEARCHING;
+ }
+
+ /**
* Get the PLMN-ID for this Network Registration, also known as the RPLMN.
*
* <p>If the device is registered, this will return the registered PLMN-ID. If registration
@@ -450,13 +483,25 @@
}
/**
- * @return {@code true} if registered on roaming network, {@code false} otherwise.
+ * @return {@code true} if registered on roaming network overridden by config. Note this value
+ * can be affected by the carrier config override.
+ *
+ * @deprecated Use {@link TelephonyDisplayInfo#isRoaming} instead.
*/
+ @Deprecated
public boolean isRoaming() {
return mRoamingType != ServiceState.ROAMING_TYPE_NOT_ROAMING;
}
/**
+ * @return {@code true} if registered on roaming network. (This value is not affected by any
+ * carrier config or resource overlay override).
+ */
+ public boolean isNetworkRoaming() {
+ return mNetworkRegistrationState == REGISTRATION_STATE_ROAMING;
+ }
+
+ /**
* @hide
* @return {@code true} if in service.
*/
@@ -486,7 +531,8 @@
}
/**
- * @return the current network roaming type.
+ * @return the current network roaming type. Note that this value can be possibly overridden by
+ * the carrier config or resource overlay.
* @hide
*/
@SystemApi
@@ -666,8 +712,8 @@
.append(" transportType=").append(
AccessNetworkConstants.transportTypeToString(mTransportType))
.append(" registrationState=").append(registrationStateToString(mRegistrationState))
- .append(" mInitialRegistrationState=")
- .append(registrationStateToString(mInitialRegistrationState))
+ .append(" networkRegistrationState=")
+ .append(registrationStateToString(mNetworkRegistrationState))
.append(" roamingType=").append(ServiceState.roamingTypeToString(mRoamingType))
.append(" accessNetworkTechnology=")
.append(TelephonyManager.getNetworkTypeName(mAccessNetworkTechnology))
@@ -688,7 +734,7 @@
@Override
public int hashCode() {
- return Objects.hash(mDomain, mTransportType, mRegistrationState, mInitialRegistrationState,
+ return Objects.hash(mDomain, mTransportType, mRegistrationState, mNetworkRegistrationState,
mRoamingType, mAccessNetworkTechnology, mRejectCause, mEmergencyOnly,
mAvailableServices, mCellIdentity, mVoiceSpecificInfo, mDataSpecificInfo, mNrState,
mRplmn, mIsUsingCarrierAggregation);
@@ -706,7 +752,7 @@
return mDomain == other.mDomain
&& mTransportType == other.mTransportType
&& mRegistrationState == other.mRegistrationState
- && mInitialRegistrationState == other.mInitialRegistrationState
+ && mNetworkRegistrationState == other.mNetworkRegistrationState
&& mRoamingType == other.mRoamingType
&& mAccessNetworkTechnology == other.mAccessNetworkTechnology
&& mRejectCause == other.mRejectCause
@@ -729,7 +775,7 @@
dest.writeInt(mDomain);
dest.writeInt(mTransportType);
dest.writeInt(mRegistrationState);
- dest.writeInt(mInitialRegistrationState);
+ dest.writeInt(mNetworkRegistrationState);
dest.writeInt(mRoamingType);
dest.writeInt(mAccessNetworkTechnology);
dest.writeInt(mRejectCause);
@@ -826,7 +872,7 @@
private int mTransportType;
@RegistrationState
- private int mInitialRegistrationState;
+ private int mNetworkRegistrationState;
@NetworkType
private int mAccessNetworkTechnology;
@@ -864,7 +910,7 @@
public Builder(@NonNull NetworkRegistrationInfo nri) {
mDomain = nri.mDomain;
mTransportType = nri.mTransportType;
- mInitialRegistrationState = nri.mInitialRegistrationState;
+ mNetworkRegistrationState = nri.mNetworkRegistrationState;
mAccessNetworkTechnology = nri.mAccessNetworkTechnology;
mRejectCause = nri.mRejectCause;
mEmergencyOnly = nri.mEmergencyOnly;
@@ -912,7 +958,7 @@
* @return The same instance of the builder.
*/
public @NonNull Builder setRegistrationState(@RegistrationState int registrationState) {
- mInitialRegistrationState = registrationState;
+ mNetworkRegistrationState = registrationState;
return this;
}
@@ -1031,7 +1077,7 @@
*/
@SystemApi
public @NonNull NetworkRegistrationInfo build() {
- return new NetworkRegistrationInfo(mDomain, mTransportType, mInitialRegistrationState,
+ return new NetworkRegistrationInfo(mDomain, mTransportType, mNetworkRegistrationState,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
mCellIdentity, mRplmn, mVoiceSpecificRegistrationInfo,
mDataSpecificRegistrationInfo);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index ac74016..03e019d 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -631,11 +631,17 @@
}
/**
- * Get current roaming indicator of phone
+ * Get current roaming indicator of phone. This roaming state could be overridden by the carrier
+ * config.
* (note: not just decoding from TS 27.007 7.2)
- *
+ * @see TelephonyDisplayInfo#isRoaming() for visualization purpose.
* @return true if TS 27.007 7.2 roaming is true
* and ONS is different from SPN
+ * @see CarrierConfigManager#KEY_FORCE_HOME_NETWORK_BOOL
+ * @see CarrierConfigManager#KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY
*/
public boolean getRoaming() {
return getVoiceRoaming() || getDataRoaming();
@@ -650,8 +656,9 @@
public boolean getVoiceRoaming() {
return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING;
}
+
/**
- * Get current voice network roaming type
+ * Get current voice roaming type. This roaming type could be overridden by the carrier config.
* @return roaming type
* @hide
*/
@@ -701,7 +708,7 @@
}
/**
- * Get current data network roaming type
+ * Get current data roaming type. This roaming type could be overridden by the carrier config.
* @return roaming type
* @hide
*/
@@ -1207,8 +1214,13 @@
/**
* Initialize the service state. Set everything to the default value.
+ *
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+ * {@link NetworkRegistrationInfo}.
*/
- private void init() {
+ private void init(boolean legacyMode) {
if (DBG) Rlog.d(LOG_TAG, "init");
mVoiceRegState = STATE_OUT_OF_SERVICE;
mDataRegState = STATE_OUT_OF_SERVICE;
@@ -1240,11 +1252,13 @@
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
.build());
- addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
- .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
- .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
- .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
- .build());
+ if (!legacyMode) {
+ addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+ .build());
+ }
}
mOperatorAlphaLongRaw = null;
mOperatorAlphaShortRaw = null;
@@ -1253,11 +1267,11 @@
}
public void setStateOutOfService() {
- init();
+ init(true);
}
public void setStateOff() {
- init();
+ init(true);
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
}
@@ -1265,11 +1279,14 @@
/**
* Set the service state to out-of-service
*
+ * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+ * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+ * is on AP-assisted mode, where IWLAN should be reported through WLAN.
* @param powerOff {@code true} if this is a power off case (i.e. Airplane mode on).
* @hide
*/
- public void setOutOfService(boolean powerOff) {
- init();
+ public void setOutOfService(boolean legacyMode, boolean powerOff) {
+ init(legacyMode);
if (powerOff) {
mVoiceRegState = STATE_POWER_OFF;
mDataRegState = STATE_POWER_OFF;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index b99f3d6..45c092e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -160,6 +160,10 @@
private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY =
"cache_key.telephony.subscription_manager_service";
+ /** The temporarily cache key to indicate whether subscription manager service is enabled. */
+ private static final String CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY =
+ "cache_key.telephony.subscription_manager_service_enabled";
+
/** @hide */
public static final String GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME = "getSimSpecificSettings";
@@ -317,6 +321,12 @@
CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY,
INVALID_PHONE_INDEX);
+ //TODO: Removed before U AOSP public release.
+ private static VoidPropertyInvalidatedCache<Boolean> sIsSubscriptionManagerServiceEnabled =
+ new VoidPropertyInvalidatedCache<>(ISub::isSubscriptionManagerServiceEnabled,
+ CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY,
+ false);
+
/**
* Generates a content {@link Uri} used to receive updates on simInfo change
* on the given subscriptionId
@@ -1116,6 +1126,14 @@
*/
public static final String USER_HANDLE = SimInfo.COLUMN_USER_HANDLE;
+ /**
+ * TelephonyProvider column name for satellite enabled.
+ * By default, it's disabled.
+ * <P>Type: INTEGER (int)</P>
+ * @hide
+ */
+ public static final String SATELLITE_ENABLED = SimInfo.COLUMN_SATELLITE_ENABLED;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"USAGE_SETTING_"},
@@ -1327,8 +1345,6 @@
private final Context mContext;
- private static boolean sIsSubscriptionManagerServiceEnabled = false;
-
// Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing
// the Context and subId.
private static final Map<Pair<Context, Integer>, Resources> sResourcesCache =
@@ -1414,9 +1430,6 @@
public SubscriptionManager(Context context) {
if (DBG) logd("SubscriptionManager created");
mContext = context;
-
- sIsSubscriptionManagerServiceEnabled = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_using_subscription_manager_service);
}
/**
@@ -1425,8 +1438,9 @@
*
* @hide
*/
+ //TODO: Removed before U AOSP public release.
public static boolean isSubscriptionManagerServiceEnabled() {
- return sIsSubscriptionManagerServiceEnabled;
+ return sIsSubscriptionManagerServiceEnabled.query(null);
}
private NetworkPolicyManager getNetworkPolicyManager() {
@@ -3939,6 +3953,13 @@
PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_PROPERTY);
}
+ /** @hide */
+ //TODO: Removed before U AOSP public release.
+ public static void invalidateSubscriptionManagerServiceEnabledCaches() {
+ PropertyInvalidatedCache.invalidateCache(
+ CACHE_KEY_SUBSCRIPTION_MANAGER_SERVICE_ENABLED_PROPERTY);
+ }
+
/**
* Allows a test process to disable client-side caching operations.
*
@@ -3960,6 +3981,8 @@
sGetSlotIndexCache.disableLocal();
sGetSubIdCache.disableLocal();
sGetPhoneIdCache.disableLocal();
+
+ sIsSubscriptionManagerServiceEnabled.disableLocal();
}
/**
@@ -3982,6 +4005,8 @@
sGetSlotIndexCache.clear();
sGetSubIdCache.clear();
sGetPhoneIdCache.clear();
+
+ sIsSubscriptionManagerServiceEnabled.clear();
}
/**
diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java
index f4e2ade..e01b10e 100644
--- a/telephony/java/android/telephony/TelephonyDisplayInfo.java
+++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java
@@ -87,10 +87,12 @@
public static final int OVERRIDE_NETWORK_TYPE_NR_ADVANCED = 5;
@NetworkType
- private final int mNetworkType;
+ private final int mNetworkType;
@OverrideNetworkType
- private final int mOverrideNetworkType;
+ private final int mOverrideNetworkType;
+
+ private final boolean mIsRoaming;
/**
* Constructor
@@ -98,18 +100,37 @@
* @param networkType Current packet-switching cellular network type
* @param overrideNetworkType The override network type
*
+ * @deprecated will not use this constructor anymore.
+ * @hide
+ */
+ @Deprecated
+ public TelephonyDisplayInfo(@NetworkType int networkType,
+ @OverrideNetworkType int overrideNetworkType) {
+ this(networkType, overrideNetworkType, false);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param networkType Current packet-switching cellular network type
+ * @param overrideNetworkType The override network type
+ * @param isRoaming True if the device is roaming after override.
+ *
* @hide
*/
public TelephonyDisplayInfo(@NetworkType int networkType,
- @OverrideNetworkType int overrideNetworkType) {
+ @OverrideNetworkType int overrideNetworkType,
+ boolean isRoaming) {
mNetworkType = networkType;
mOverrideNetworkType = overrideNetworkType;
+ mIsRoaming = isRoaming;
}
/** @hide */
public TelephonyDisplayInfo(Parcel p) {
mNetworkType = p.readInt();
mOverrideNetworkType = p.readInt();
+ mIsRoaming = p.readBoolean();
}
/**
@@ -135,10 +156,25 @@
return mOverrideNetworkType;
}
+ /**
+ * Get device is roaming or not. Note the isRoaming is for market branding or visualization
+ * purposes only. It cannot be treated as the actual roaming device is camped on.
+ *
+ * @return True if the device is registered on roaming network overridden by config.
+ * @see CarrierConfigManager#KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY
+ * @see CarrierConfigManager#KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY
+ */
+ public boolean isRoaming() {
+ return mIsRoaming;
+ }
+
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mNetworkType);
dest.writeInt(mOverrideNetworkType);
+ dest.writeBoolean(mIsRoaming);
}
public static final @NonNull Parcelable.Creator<TelephonyDisplayInfo> CREATOR =
@@ -165,12 +201,13 @@
if (o == null || getClass() != o.getClass()) return false;
TelephonyDisplayInfo that = (TelephonyDisplayInfo) o;
return mNetworkType == that.mNetworkType
- && mOverrideNetworkType == that.mOverrideNetworkType;
+ && mOverrideNetworkType == that.mOverrideNetworkType
+ && mIsRoaming == that.mIsRoaming;
}
@Override
public int hashCode() {
- return Objects.hash(mNetworkType, mOverrideNetworkType);
+ return Objects.hash(mNetworkType, mOverrideNetworkType, mIsRoaming);
}
/**
@@ -195,6 +232,7 @@
@Override
public String toString() {
return "TelephonyDisplayInfo {network=" + TelephonyManager.getNetworkTypeName(mNetworkType)
- + ", override=" + overrideNetworkTypeToString(mOverrideNetworkType) + "}";
+ + ", overrideNetwork=" + overrideNetworkTypeToString(mOverrideNetworkType)
+ + ", isRoaming=" + mIsRoaming + "}";
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fd5ec25..fa60031 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -311,6 +311,31 @@
public static final int SRVCC_STATE_HANDOVER_CANCELED = 3;
/**
+ * Convert srvcc handover state to string.
+ *
+ * @param state The srvcc handover state.
+ * @return The srvcc handover state in string format.
+ *
+ * @hide
+ */
+ public static @NonNull String srvccStateToString(int state) {
+ switch (state) {
+ case TelephonyManager.SRVCC_STATE_HANDOVER_NONE:
+ return "NONE";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_STARTED:
+ return "STARTED";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED:
+ return "COMPLETED";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_FAILED:
+ return "FAILED";
+ case TelephonyManager.SRVCC_STATE_HANDOVER_CANCELED:
+ return "CANCELED";
+ default:
+ return "UNKNOWN(" + state + ")";
+ }
+ }
+
+ /**
* A UICC card identifier used if the device does not support the operation.
* For example, {@link #getCardIdForDefaultEuicc()} returns this value if the device has no
* eUICC, or the eUICC cannot be read.
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 19f2a9b..b761709 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -153,8 +153,9 @@
nsi = mScanInfo.get(message.arg2);
}
if (nsi == null) {
- throw new RuntimeException(
- "Failed to find NetworkScanInfo with id " + message.arg2);
+ Rlog.e(TAG, "Unexpceted message " + message.what
+ + " as there is no NetworkScanInfo with id " + message.arg2);
+ return;
}
final NetworkScanCallback callback = nsi.mCallback;
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 25a714a..defa046 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -356,4 +356,11 @@
* @hide
*/
List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser(in UserHandle userHandle);
+
+ /**
+ * @return {@code true} if using SubscriptionManagerService instead of
+ * SubscriptionController.
+ */
+ //TODO: Removed before U AOSP public release.
+ boolean isSubscriptionManagerServiceEnabled();
}
diff --git a/tests/ActivityManagerPerfTests/utils/Android.bp b/tests/ActivityManagerPerfTests/utils/Android.bp
index 99c43c8..5902c1c 100644
--- a/tests/ActivityManagerPerfTests/utils/Android.bp
+++ b/tests/ActivityManagerPerfTests/utils/Android.bp
@@ -32,6 +32,6 @@
static_libs: [
"androidx.test.rules",
"junit",
- "ub-uiautomator",
+ "androidx.test.uiautomator_uiautomator",
],
}
diff --git a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
index fc787ba..9bd94f2 100644
--- a/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
+++ b/tests/ActivityManagerPerfTests/utils/src/com/android/frameworks/perftests/am/util/Utils.java
@@ -19,10 +19,10 @@
import android.content.Intent;
import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.support.test.uiautomator.UiDevice;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
import java.io.IOException;
diff --git a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
index 5430dee..afa4ff8 100644
--- a/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
+++ b/tests/DynamicCodeLoggerIntegrationTests/src/com/android/server/pm/dex/DynamicCodeLoggerIntegrationTests.java
@@ -84,7 +84,7 @@
// avoid flakiness we run these tests multiple times, allowing progressively longer between
// code loading and checking the logs on each try.)
private static final int AUDIT_LOG_RETRIES = 10;
- private static final int RETRY_DELAY_MS = 2_000;
+ private static final int RETRY_DELAY_MS = 500;
private static Context sContext;
private static int sMyUid;
@@ -245,7 +245,7 @@
"/DynamicCodeLoggerNativeExecutable", privateCopyFile);
EventLog.writeEvent(EventLog.getTagCode("auditd"),
- "type=1400 avc: granted { execute_no_trans } "
+ "type=1400 avc: granted { execute_no_trans } "
+ "path=\"" + privateCopyFile + "\" "
+ "scontext=u:r:untrusted_app: "
+ "tcontext=u:object_r:app_data_file: "
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 7731e09..5301d67 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -47,6 +47,9 @@
"launcher-aosp-tapl",
"platform-test-annotations",
],
+ data: [
+ ":FlickerTestApp",
+ ],
}
java_library {
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index de9bbb6..a92a6ae 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -21,7 +21,7 @@
"services.core.unboosted",
"testables",
"truth-prebuilt",
- "ub-uiautomator",
+ "androidx.test.uiautomator_uiautomator",
],
test_suites: ["device-tests"],
}
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index 1d65cc3..8025406 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -27,14 +27,15 @@
import android.os.SystemClock
import android.provider.Settings
import android.provider.Settings.Global.HIDE_ERROR_DIALOGS
-import android.support.test.uiautomator.By
-import android.support.test.uiautomator.UiDevice
-import android.support.test.uiautomator.UiObject2
-import android.support.test.uiautomator.Until
import android.testing.PollingCheck
import android.view.InputDevice
import android.view.MotionEvent
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp
index de86498..a5c6d65 100644
--- a/tests/OdmApps/Android.bp
+++ b/tests/OdmApps/Android.bp
@@ -26,4 +26,8 @@
srcs: ["src/**/*.java"],
libs: ["tradefed"],
test_suites: ["device-tests"],
+ data: [
+ ":TestOdmApp",
+ ":TestOdmPrivApp",
+ ],
}
diff --git a/tests/SharedLibraryLoadingTest/AndroidTest.xml b/tests/SharedLibraryLoadingTest/AndroidTest.xml
index 947453d..ad05847 100644
--- a/tests/SharedLibraryLoadingTest/AndroidTest.xml
+++ b/tests/SharedLibraryLoadingTest/AndroidTest.xml
@@ -22,7 +22,6 @@
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
- <option name="cleanup" value="false" />
<option name="remount-system" value="true" />
<option name="push"
value="SharedLibraryLoadingTests_StandardSharedLibrary.apk->/product/app/SharedLibraryLoadingTests_StandardSharedLibrary.apk" />
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
index 9db19a3..a0fcfc5 100644
--- a/tests/SoundTriggerTestApp/OWNERS
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -1,2 +1,2 @@
-include /core/java/android/media/soundtrigger/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
mdooley@google.com
diff --git a/tests/SoundTriggerTests/OWNERS b/tests/SoundTriggerTests/OWNERS
index 816bc6b..1e41886 100644
--- a/tests/SoundTriggerTests/OWNERS
+++ b/tests/SoundTriggerTests/OWNERS
@@ -1 +1 @@
-include /core/java/android/media/soundtrigger/OWNERS
+include /media/java/android/media/soundtrigger/OWNERS
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index cce0dde..38e7447 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -55,6 +55,7 @@
"cts-install-lib-host",
],
data: [
+ ":StagedInstallInternalTestApp",
":apex.apexd_test",
":com.android.apex.apkrollback.test_v1",
":StagedInstallTestApexV2",
diff --git a/tests/SystemMemoryTest/host/Android.bp b/tests/SystemMemoryTest/host/Android.bp
index 7974462..cc8bc45 100644
--- a/tests/SystemMemoryTest/host/Android.bp
+++ b/tests/SystemMemoryTest/host/Android.bp
@@ -26,4 +26,7 @@
srcs: ["src/**/*.java"],
libs: ["tradefed"],
test_suites: ["general-tests"],
+ data: [
+ ":SystemMemoryTestDevice",
+ ],
}
diff --git a/tests/WindowAnimationJank/Android.bp b/tests/WindowAnimationJank/Android.bp
index ed86aa5..8542f88 100644
--- a/tests/WindowAnimationJank/Android.bp
+++ b/tests/WindowAnimationJank/Android.bp
@@ -25,7 +25,7 @@
name: "WindowAnimationJank",
srcs: ["src/**/*.java"],
static_libs: [
- "ub-uiautomator",
+ "androidx.test.uiautomator_uiautomator",
"androidx.test.janktesthelper",
"junit",
],
diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java
index 2531464..48a359c 100644
--- a/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java
+++ b/tests/WindowAnimationJank/src/android/windowanimationjank/Utils.java
@@ -18,11 +18,12 @@
import android.content.ComponentName;
import android.content.Intent;
import android.os.SystemClock;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
+
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
/**
* Set of helpers to manipulate test activities.
diff --git a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
index a8ace162..cb7c511 100644
--- a/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
+++ b/tests/WindowAnimationJank/src/android/windowanimationjank/WindowAnimationJankTestBase.java
@@ -16,9 +16,8 @@
package android.windowanimationjank;
-import android.support.test.uiautomator.UiDevice;
-
import androidx.test.jank.JankTestBase;
+import androidx.test.uiautomator.UiDevice;
/**
* This adds additional system level jank monitor and its result is merged with primary monitor
diff --git a/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
new file mode 100644
index 0000000..d10ae30
--- /dev/null
+++ b/tests/utils/testutils/java/android/os/test/FakePermissionEnforcer.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.test;
+
+import static android.permission.PermissionManager.PERMISSION_GRANTED;
+import static android.permission.PermissionManager.PERMISSION_HARD_DENIED;
+
+import android.annotation.NonNull;
+import android.content.AttributionSource;
+import android.os.PermissionEnforcer;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Fake for {@link PermissionEnforcer}. Useful for tests wanting to mock the
+ * permission checks of an AIDL service. FakePermissionEnforcer may be passed
+ * to the constructor of the AIDL-generated Stub class.
+ *
+ */
+public class FakePermissionEnforcer extends PermissionEnforcer {
+ private Set<String> mGranted;
+
+ public FakePermissionEnforcer() {
+ mGranted = new HashSet();
+ }
+
+ public void grant(String permission) {
+ mGranted.add(permission);
+ }
+
+ public void revoke(String permission) {
+ mGranted.remove(permission);
+ }
+
+ public void revokeAll() {
+ mGranted.clear();
+ }
+
+ private boolean granted(String permission) {
+ return mGranted.contains(permission);
+ }
+
+ @Override
+ protected int checkPermission(@NonNull String permission,
+ @NonNull AttributionSource source) {
+ return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+
+ @Override
+ protected int checkPermission(@NonNull String permission, int pid, int uid) {
+ return granted(permission) ? PERMISSION_GRANTED : PERMISSION_HARD_DENIED;
+ }
+}
diff --git a/tests/utils/testutils/java/android/os/test/OWNERS b/tests/utils/testutils/java/android/os/test/OWNERS
new file mode 100644
index 0000000..3a9129e
--- /dev/null
+++ b/tests/utils/testutils/java/android/os/test/OWNERS
@@ -0,0 +1 @@
+per-file FakePermissionEnforcer.java = file:/tests/EnforcePermission/OWNERS
diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
index b313c9f..73a0a61 100644
--- a/tests/vcn/java/android/net/vcn/VcnConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
@@ -17,6 +17,7 @@
package android.net.vcn;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static org.junit.Assert.assertEquals;
@@ -160,6 +161,37 @@
assertNotEquals(config, configNotEqual);
}
+ private VcnConfig buildConfigRestrictTransportTest(boolean isTestMode) throws Exception {
+ VcnConfig.Builder builder =
+ new VcnConfig.Builder(mContext)
+ .setRestrictedUnderlyingNetworkTransports(Set.of(TRANSPORT_TEST));
+ if (isTestMode) {
+ builder.setIsTestModeProfile();
+ }
+
+ for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) {
+ builder.addGatewayConnectionConfig(gatewayConnectionConfig);
+ }
+
+ return builder.build();
+ }
+
+ @Test
+ public void testRestrictTransportTestInTestModeProfile() throws Exception {
+ final VcnConfig config = buildConfigRestrictTransportTest(true /* isTestMode */);
+ assertEquals(Set.of(TRANSPORT_TEST), config.getRestrictedUnderlyingNetworkTransports());
+ }
+
+ @Test
+ public void testRestrictTransportTestInNonTestModeProfile() throws Exception {
+ try {
+ buildConfigRestrictTransportTest(false /* isTestMode */);
+ fail("Expected exception because the config is not a test mode profile");
+ } catch (Exception expected) {
+
+ }
+ }
+
@Test
public void testParceling() {
final VcnConfig config = buildTestConfig(mContext);
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 075bc5e..4123f80 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -17,7 +17,9 @@
package com.android.server;
import static android.net.ConnectivityManager.NetworkCallback;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -67,7 +69,6 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.TelephonyNetworkSpecifier;
import android.net.Uri;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
@@ -128,6 +129,15 @@
private static final VcnConfig TEST_VCN_CONFIG;
private static final VcnConfig TEST_VCN_CONFIG_PKG_2;
private static final int TEST_UID = Process.FIRST_APPLICATION_UID;
+ private static final String TEST_IFACE_NAME = "TEST_IFACE";
+ private static final String TEST_IFACE_NAME_2 = "TEST_IFACE2";
+ private static final LinkProperties TEST_LP_1 = new LinkProperties();
+ private static final LinkProperties TEST_LP_2 = new LinkProperties();
+
+ static {
+ TEST_LP_1.setInterfaceName(TEST_IFACE_NAME);
+ TEST_LP_2.setInterfaceName(TEST_IFACE_NAME_2);
+ }
static {
final Context mockConfigContext = mock(Context.class);
@@ -1034,8 +1044,7 @@
setupSubscriptionAndStartVcn(subId, subGrp, isVcnActive);
return mVcnMgmtSvc.getUnderlyingNetworkPolicy(
- getNetworkCapabilitiesBuilderForTransport(subId, transport).build(),
- new LinkProperties());
+ getNetworkCapabilitiesBuilderForTransport(subId, transport).build(), TEST_LP_1);
}
private void checkGetRestrictedTransportsFromCarrierConfig(
@@ -1260,7 +1269,7 @@
false /* expectRestricted */);
}
- private void setupTrackedCarrierWifiNetwork(NetworkCapabilities caps) {
+ private void setupTrackedNetwork(NetworkCapabilities caps, LinkProperties lp) {
mVcnMgmtSvc.systemReady();
final ArgumentCaptor<NetworkCallback> captor =
@@ -1269,7 +1278,10 @@
.registerNetworkCallback(
eq(new NetworkRequest.Builder().clearCapabilities().build()),
captor.capture());
- captor.getValue().onCapabilitiesChanged(mock(Network.class, CALLS_REAL_METHODS), caps);
+
+ Network mockNetwork = mock(Network.class, CALLS_REAL_METHODS);
+ captor.getValue().onCapabilitiesChanged(mockNetwork, caps);
+ captor.getValue().onLinkPropertiesChanged(mockNetwork, lp);
}
@Test
@@ -1279,7 +1291,7 @@
getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
// Trigger test without VCN instance alive; expect restart due to change of NOT_RESTRICTED
// immutable capability
@@ -1288,7 +1300,7 @@
getNetworkCapabilitiesBuilderForTransport(
TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.build(),
- new LinkProperties());
+ TEST_LP_1);
assertTrue(policy.isTeardownRequested());
}
@@ -1298,7 +1310,7 @@
final NetworkCapabilities existingNetworkCaps =
getNetworkCapabilitiesBuilderForTransport(TEST_SUBSCRIPTION_ID, TRANSPORT_WIFI)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
final VcnUnderlyingNetworkPolicy policy =
startVcnAndGetPolicyForTransport(
@@ -1315,7 +1327,7 @@
.addCapability(NET_CAPABILITY_NOT_RESTRICTED)
.removeCapability(NET_CAPABILITY_IMS)
.build();
- setupTrackedCarrierWifiNetwork(existingNetworkCaps);
+ setupTrackedNetwork(existingNetworkCaps, TEST_LP_1);
final VcnUnderlyingNetworkPolicy policy =
mVcnMgmtSvc.getUnderlyingNetworkPolicy(
@@ -1336,7 +1348,7 @@
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
- .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUBSCRIPTION_ID_2))
+ .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2))
.build();
VcnUnderlyingNetworkPolicy policy =
@@ -1346,6 +1358,38 @@
assertEquals(nc, policy.getMergedNetworkCapabilities());
}
+ /**
+ * Checks that networks with similar capabilities do not clobber each other.
+ *
+ * <p>In previous iterations, the VcnMgmtSvc used capability-matching to check if a network
+ * undergoing policy checks were the same as an existing networks. However, this meant that if
+ * there were newly added capabilities that the VCN did not check, two networks differing only
+ * by that capability would restart each other constantly.
+ */
+ @Test
+ public void testGetUnderlyingNetworkPolicySimilarNetworks() throws Exception {
+ NetworkCapabilities nc1 =
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .setSubscriptionIds(Collections.singleton(TEST_SUBSCRIPTION_ID_2))
+ .build();
+
+ NetworkCapabilities nc2 =
+ new NetworkCapabilities.Builder(nc1)
+ .addCapability(NET_CAPABILITY_ENTERPRISE)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ .build();
+
+ setupTrackedNetwork(nc1, TEST_LP_1);
+
+ VcnUnderlyingNetworkPolicy policy = mVcnMgmtSvc.getUnderlyingNetworkPolicy(nc2, TEST_LP_2);
+
+ assertFalse(policy.isTeardownRequested());
+ assertEquals(nc2, policy.getMergedNetworkCapabilities());
+ }
+
@Test(expected = SecurityException.class)
public void testGetUnderlyingNetworkPolicyInvalidPermission() {
doReturn(PackageManager.PERMISSION_DENIED)
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
index 629e988..2266041 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
@@ -95,6 +95,7 @@
private static final NetworkCapabilities WIFI_NETWORK_CAPABILITIES =
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setSignalStrength(WIFI_RSSI)
.setSsid(SSID)
.setLinkUpstreamBandwidthKbps(LINK_UPSTREAM_BANDWIDTH_KBPS)
@@ -509,12 +510,14 @@
VcnCellUnderlyingNetworkTemplate template, boolean expectMatch) {
assertEquals(
expectMatch,
- checkMatchesCellPriorityRule(
+ checkMatchesPriorityRule(
mVcnContext,
template,
mCellNetworkRecord,
SUB_GROUP,
- mSubscriptionSnapshot));
+ mSubscriptionSnapshot,
+ null /* currentlySelected */,
+ null /* carrierConfig */));
}
@Test
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 34e8edb..e7b3770 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -26,8 +26,8 @@
namespace aapt {
static ApiVersion sDevelopmentSdkLevel = 10000;
-static const auto sDevelopmentSdkCodeNames =
- std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake"});
+static const auto sDevelopmentSdkCodeNames = std::unordered_set<StringPiece>(
+ {"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake", "VanillaIceCream"});
static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
{0x021c, 1},
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 0170c4a..2f5d8d1 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -206,6 +206,11 @@
AddOptionalFlag("--compile-sdk-version-name",
"Version name to inject into the AndroidManifest.xml if none is present.",
&options_.manifest_fixer_options.compile_sdk_version_codename);
+ AddOptionalSwitch(
+ "--no-compile-sdk-metadata",
+ "Suppresses output of compile SDK-related attributes in AndroidManifest.xml,\n"
+ "including android:compileSdkVersion and platformBuildVersion.",
+ &options_.manifest_fixer_options.no_compile_sdk_metadata);
AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.",
&shared_lib_);
AddOptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib_);
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 4219191..f8e7347 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -635,7 +635,7 @@
root->InsertChild(0, std::move(uses_sdk));
}
- if (options_.compile_sdk_version) {
+ if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version) {
xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
// Make sure we un-compile the value if it was set to something else.
@@ -647,10 +647,9 @@
// Make sure we un-compile the value if it was set to something else.
attr->compiled_value = {};
attr->value = options_.compile_sdk_version.value();
-
}
- if (options_.compile_sdk_version_codename) {
+ if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version_codename) {
xml::Attribute* attr =
root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index a8707d9..70bfcfc 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -68,11 +68,12 @@
std::optional<std::string> revision_code_default;
// The version of the framework being compiled against to set for 'android:compileSdkVersion' in
- // the <manifest> tag.
+ // the <manifest> tag. Not used if no_compile_sdk_metadata is set.
std::optional<std::string> compile_sdk_version;
// The version codename of the framework being compiled against to set for
- // 'android:compileSdkVersionCodename' in the <manifest> tag.
+ // 'android:compileSdkVersionCodename' in the <manifest> tag. Not used if no_compile_sdk_metadata
+ // is set.
std::optional<std::string> compile_sdk_version_codename;
// Whether validation errors should be treated only as warnings. If this is 'true', then an
@@ -85,6 +86,9 @@
// Whether to replace the manifest version with the the command line version
bool replace_version = false;
+
+ // Whether to suppress `android:compileSdkVersion*` and `platformBuildVersion*` attributes.
+ bool no_compile_sdk_metadata = false;
};
// Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 098d0be..9204d22 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -892,6 +892,35 @@
EXPECT_THAT(attr->value, StrEq("P"));
}
+TEST_F(ManifestFixerTest, DoNotInsertCompileSdkVersions) {
+ std::string input = R"(<manifest package="com.pkg" />)";
+ ManifestFixerOptions options;
+ options.no_compile_sdk_metadata = true;
+ options.compile_sdk_version = {"28"};
+ options.compile_sdk_version_codename = {"P"};
+
+ std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options);
+ ASSERT_THAT(manifest, NotNull());
+
+ // There should be a declaration of kSchemaAndroid, even when the input
+ // didn't have one.
+ EXPECT_EQ(manifest->root->namespace_decls.size(), 1);
+ EXPECT_EQ(manifest->root->namespace_decls[0].prefix, "android");
+ EXPECT_EQ(manifest->root->namespace_decls[0].uri, xml::kSchemaAndroid);
+
+ xml::Attribute* attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersion");
+ ASSERT_THAT(attr, IsNull());
+
+ attr = manifest->root->FindAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
+ ASSERT_THAT(attr, IsNull());
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionCode");
+ ASSERT_THAT(attr, IsNull());
+
+ attr = manifest->root->FindAttribute("", "platformBuildVersionName");
+ ASSERT_THAT(attr, IsNull());
+}
+
TEST_F(ManifestFixerTest, OverrideCompileSdkVersions) {
std::string input = R"(
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android"
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index dd266ff..a2c1d6b 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -383,13 +383,11 @@
if (allDefaults) return false;
emptyline();
- int policyCount = 0;
printf("Privacy* %s[] = {\n", messageName.c_str());
for (size_t i=0; i<fieldsInOrder.size(); i++) {
const FieldDescriptor* field = fieldsInOrder[i];
if (hasDefaultFlags[i]) continue; // NOLINT(clang-analyzer-core.uninitialized.Branch)
printf(" &%s,\n", getFieldName(field).c_str());
- policyCount++;
}
printf(" NULL };\n");
emptyline();
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
index dcfbe95..e03d92ab 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt
@@ -72,5 +72,78 @@
"Status",
"IThermalService",
"IPowerManager",
- "ITunerResourceManager"
+ "ITunerResourceManager",
+ // b/278147400
+ "IActivityManager",
+ "IUidObserver",
+ "IDrm",
+ "IVsyncCallback",
+ "IVsyncService",
+ "ICallback",
+ "IIPCTest",
+ "ISafeInterfaceTest",
+ "IGpuService",
+ "IConsumerListener",
+ "IGraphicBufferConsumer",
+ "ITransactionComposerListener",
+ "SensorEventConnection",
+ "SensorServer",
+ "ICamera",
+ "ICameraClient",
+ "ICameraRecordingProxy",
+ "ICameraRecordingProxyListener",
+ "ICrypto",
+ "IOMXObserver",
+ "IStreamListener",
+ "IStreamSource",
+ "IAudioService",
+ "IDataSource",
+ "IDrmClient",
+ "IMediaCodecList",
+ "IMediaDrmService",
+ "IMediaExtractor",
+ "IMediaExtractorService",
+ "IMediaHTTPConnection",
+ "IMediaHTTPService",
+ "IMediaLogService",
+ "IMediaMetadataRetriever",
+ "IMediaMetricsService",
+ "IMediaPlayer",
+ "IMediaPlayerClient",
+ "IMediaPlayerService",
+ "IMediaRecorder",
+ "IMediaRecorderClient",
+ "IMediaResourceMonitor",
+ "IMediaSource",
+ "IRemoteDisplay",
+ "IRemoteDisplayClient",
+ "IResourceManagerClient",
+ "IResourceManagerService",
+ "IComplexTypeInterface",
+ "IPermissionController",
+ "IPingResponder",
+ "IProcessInfoService",
+ "ISchedulingPolicyService",
+ "IStringConstants",
+ "IObbActionListener",
+ "IStorageEventListener",
+ "IStorageManager",
+ "IStorageShutdownObserver",
+ "IPersistentVrStateCallbacks",
+ "IVrManager",
+ "IVrStateCallbacks",
+ "ISurfaceComposer",
+ "IMemory",
+ "IMemoryHeap",
+ "IProcfsInspector",
+ "IAppOpsCallback",
+ "IAppOpsService",
+ "IBatteryStats",
+ "IResultReceiver",
+ "IShellCallback",
+ "IDrmManagerService",
+ "IDrmServiceListener",
+ "IAAudioClient",
+ "IAAudioService",
+ "VtsFuzzer",
)