Merge "Fix AudioDeviceAttributes null crash" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 21b1b17..f69fd55 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -303,6 +303,7 @@
aconfig_declarations {
name: "android.security.flags-aconfig",
package: "android.security",
+ exportable: true,
container: "system",
srcs: ["core/java/android/security/*.aconfig"],
}
@@ -320,6 +321,19 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+java_aconfig_library {
+ name: "android.security.flags-aconfig-java-export",
+ aconfig_declarations: "android.security.flags-aconfig",
+ mode: "exported",
+ min_sdk_version: "30",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.tethering",
+ "com.android.wifi",
+ ],
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
cc_aconfig_library {
name: "android_security_flags_aconfig_c_lib",
aconfig_declarations: "android.security.flags-aconfig",
diff --git a/OWNERS b/OWNERS
index d0a634e..058ea36 100644
--- a/OWNERS
+++ b/OWNERS
@@ -34,6 +34,8 @@
per-file *ravenwood* = file:ravenwood/OWNERS
per-file *Ravenwood* = file:ravenwood/OWNERS
+per-file PREUPLOAD.cfg = file:/PREUPLOAD_OWNERS
+
per-file INPUT_OWNERS = file:/INPUT_OWNERS
per-file ZYGOTE_OWNERS = file:/ZYGOTE_OWNERS
per-file SQLITE_OWNERS = file:/SQLITE_OWNERS
@@ -48,3 +50,4 @@
per-file ADPF_OWNERS = file:/ADPF_OWNERS
per-file GAME_MANAGER_OWNERS = file:/GAME_MANAGER_OWNERS
per-file SDK_OWNERS = file:/SDK_OWNERS
+per-file PREUPLOAD_OWNERS = file:/PREUPLOAD_OWNERS
diff --git a/PREUPLOAD_OWNERS b/PREUPLOAD_OWNERS
new file mode 100644
index 0000000..ece4d3e
--- /dev/null
+++ b/PREUPLOAD_OWNERS
@@ -0,0 +1,2 @@
+roosa@google.com
+gsennton@google.com
diff --git a/apct-tests/perftests/core/src/android/content/pm/SystemFeaturesMetadataPerfTest.java b/apct-tests/perftests/core/src/android/content/pm/SystemFeaturesMetadataPerfTest.java
new file mode 100644
index 0000000..205c7b8
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/content/pm/SystemFeaturesMetadataPerfTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class SystemFeaturesMetadataPerfTest {
+ // As each query is relatively cheap, add an inner iteration loop to reduce execution noise.
+ private static final int NUM_ITERATIONS = 10;
+
+ @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Test
+ public void maybeGetSdkFeatureIndex_featureDefined() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < NUM_ITERATIONS; ++i) {
+ PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_WATCH);
+ PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_LEANBACK);
+ PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_IPSEC_TUNNELS);
+ PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_WEBVIEW);
+ PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_NFC_BEAM);
+ PackageManager.maybeGetSdkFeatureIndex(PackageManager.FEATURE_AUTOFILL);
+ }
+ }
+ }
+
+ @Test
+ public void maybeGetSdkFeatureIndex_featureUndefined() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < NUM_ITERATIONS; ++i) {
+ PackageManager.maybeGetSdkFeatureIndex("com.android.custom.feature.1");
+ PackageManager.maybeGetSdkFeatureIndex("com.android.custom.feature.2");
+ PackageManager.maybeGetSdkFeatureIndex("foo");
+ PackageManager.maybeGetSdkFeatureIndex("bar");
+ PackageManager.maybeGetSdkFeatureIndex("0");
+ PackageManager.maybeGetSdkFeatureIndex("");
+ }
+ }
+ }
+
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
index ed669be..c775280 100644
--- a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
@@ -63,14 +63,12 @@
@Test
@Parameters(method = "getData")
- public void timeZipFileOpen(int numEntries) throws Exception {
+ public void timeZipFileOpenClose(int numEntries) throws Exception {
setUp(numEntries);
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
ZipFile zf = new ZipFile(mFile);
- state.pauseTiming();
zf.close();
- state.resumeTiming();
}
}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
index 73bff08..af02374 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java
@@ -20,6 +20,7 @@
import android.app.Instrumentation;
import android.os.Bundle;
import android.os.Debug;
+import android.os.Trace;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -129,17 +130,23 @@
}
private void beginWarmup() {
+ Trace.beginSection("Warmup");
mStartTimeNs = System.nanoTime();
mIteration = 0;
mState = WARMUP;
}
+ private void endWarmup() {
+ Trace.endSection();
+ }
+
private void beginBenchmark(long warmupDuration, int iterations) {
if (ENABLE_PROFILING) {
File f = new File(InstrumentationRegistry.getContext().getDataDir(), "benchprof");
Log.d(TAG, "Tracing to: " + f.getAbsolutePath());
Debug.startMethodTracingSampling(f.getAbsolutePath(), 16 * 1024 * 1024, 100);
}
+ Trace.beginSection("Benchmark");
mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
@@ -150,6 +157,10 @@
mStartTimeNs = System.nanoTime();
}
+ private void endBenchmark() {
+ Trace.endSection();
+ }
+
private boolean startNextTestRun() {
final long currentTime = System.nanoTime();
mResults.add((currentTime - mStartTimeNs - mPausedDurationNs) / mMaxIterations);
@@ -165,6 +176,7 @@
return true;
}
mState = FINISHED;
+ endBenchmark();
return false;
}
mPausedDurationNs = 0;
@@ -189,6 +201,7 @@
// don't yet have a target iteration count.
final long duration = System.nanoTime() - mStartTimeNs;
if (mIteration >= WARMUP_MIN_ITERATIONS && duration >= WARMUP_DURATION_NS) {
+ endWarmup();
beginBenchmark(duration, mIteration);
}
return true;
@@ -208,6 +221,7 @@
mCustomizedIterations++;
if (mCustomizedIterations >= mMaxCustomizedIterations) {
mState = FINISHED;
+ endBenchmark();
return false;
}
mCustomizedIterationListener.onStart(mCustomizedIterations);
diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp
index 1ebe0cd..796c841 100644
--- a/api/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -129,6 +129,10 @@
droidstubs {
name: "framework-doc-stubs",
defaults: ["android-non-updatable-doc-stubs-defaults"],
+ flags: [
+ // Ignore any compatibility errors, see check_api.last_released below for more information.
+ "--hide-category Compatibility",
+ ],
srcs: [":all-modules-public-stubs-source-exportable"],
api_levels_module: "api_versions_public",
aidl: {
@@ -137,13 +141,39 @@
"packages/modules/Media/apex/aidl/stable",
],
},
+
+ // Pass the previously released API to support reverting flagged APIs. Without this, reverting
+ // a flagged API will cause it to be removed, even if it had previously been released. This
+ // has the side effect of causing compatibility issues to be reported but they are already
+ // checked elsewhere so they will be ignored, see `--hide-category Compatibility` above.
+ check_api: {
+ last_released: {
+ api_file: ":android.api.combined.public.latest",
+ removed_api_file: ":android-removed.api.combined.public.latest",
+ },
+ },
}
droidstubs {
name: "framework-doc-system-stubs",
defaults: ["framework-doc-stubs-sources-default"],
- flags: ["--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)"],
+ flags: [
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\)",
+ // Ignore any compatibility errors, see check_api.last_released below for more information.
+ "--hide-category Compatibility",
+ ],
api_levels_module: "api_versions_system",
+
+ // Pass the previously released API to support reverting flagged APIs. Without this, reverting
+ // a flagged API will cause it to be removed, even if it had previously been released. This
+ // has the side effect of causing compatibility issues to be reported but they are already
+ // checked elsewhere so they will be ignored, see `--hide-category Compatibility` above.
+ check_api: {
+ last_released: {
+ api_file: ":android.api.combined.system.latest",
+ removed_api_file: ":android-removed.api.combined.system.latest",
+ },
+ },
}
/////////////////////////////////////////////////////////////////////
diff --git a/core/api/current.txt b/core/api/current.txt
index e3a2455..16852ae 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -13034,6 +13034,7 @@
method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle, @Nullable android.graphics.Rect, int);
method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedIcon(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle);
method @NonNull public abstract CharSequence getUserBadgedLabel(@NonNull CharSequence, @NonNull android.os.UserHandle);
+ method @FlaggedApi("android.content.pm.cloud_compilation_pm") @NonNull public static android.content.pm.SigningInfo getVerifiedSigningInfo(@NonNull String, int) throws android.content.pm.SigningInfoException;
method @NonNull @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions(@NonNull String, int);
method @Nullable public abstract android.content.res.XmlResourceParser getXml(@NonNull String, @XmlRes int, @Nullable android.content.pm.ApplicationInfo);
method public boolean hasSigningCertificate(@NonNull String, @NonNull byte[], int);
@@ -13672,8 +13673,17 @@
method public android.content.pm.Signature[] getSigningCertificateHistory();
method public boolean hasMultipleSigners();
method public boolean hasPastSigningCertificates();
+ method @FlaggedApi("android.content.pm.cloud_compilation_pm") public boolean signersMatchExactly(@NonNull android.content.pm.SigningInfo);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.SigningInfo> CREATOR;
+ field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_JAR = 1; // 0x1
+ field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V2 = 2; // 0x2
+ field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V3 = 3; // 0x3
+ field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V4 = 4; // 0x4
+ }
+
+ @FlaggedApi("android.content.pm.cloud_compilation_pm") public class SigningInfoException extends java.lang.Exception {
+ method @FlaggedApi("android.content.pm.cloud_compilation_pm") public int getCode();
}
public final class VersionedPackage implements android.os.Parcelable {
@@ -48167,7 +48177,7 @@
method public static void dumpSpans(CharSequence, android.util.Printer, String);
method public static CharSequence ellipsize(CharSequence, android.text.TextPaint, float, android.text.TextUtils.TruncateAt);
method public static CharSequence ellipsize(CharSequence, android.text.TextPaint, float, android.text.TextUtils.TruncateAt, boolean, @Nullable android.text.TextUtils.EllipsizeCallback);
- method public static boolean equals(CharSequence, CharSequence);
+ method public static boolean equals(@Nullable CharSequence, @Nullable CharSequence);
method public static CharSequence expandTemplate(CharSequence, java.lang.CharSequence...);
method public static int getCapsMode(CharSequence, int, int);
method public static void getChars(CharSequence, int, int, char[], int);
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 5790a73..b2331cb 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -129,7 +129,6 @@
public abstract class PackageManager {
method @NonNull public String getSdkSandboxPackageName();
- method @FlaggedApi("android.content.pm.cloud_compilation_pm") @NonNull public static android.content.pm.SigningInfo getVerifiedSigningInfo(@NonNull String, int) throws android.content.pm.SigningInfoException;
method @RequiresPermission(android.Manifest.permission.MAKE_UID_VISIBLE) public void makeUidVisible(int, int);
field public static final String EXTRA_VERIFICATION_ROOT_HASH = "android.content.pm.extra.VERIFICATION_ROOT_HASH";
field public static final int MATCH_STATIC_SHARED_AND_SDK_LIBRARIES = 67108864; // 0x4000000
@@ -140,18 +139,6 @@
method @NonNull public String getPackageName();
}
- public final class SigningInfo implements android.os.Parcelable {
- method @FlaggedApi("android.content.pm.cloud_compilation_pm") public boolean signersMatchExactly(@NonNull android.content.pm.SigningInfo);
- field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_JAR = 1; // 0x1
- field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V2 = 2; // 0x2
- field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V3 = 3; // 0x3
- field @FlaggedApi("android.content.pm.cloud_compilation_pm") public static final int VERSION_SIGNING_BLOCK_V4 = 4; // 0x4
- }
-
- @FlaggedApi("android.content.pm.cloud_compilation_pm") public class SigningInfoException extends java.lang.Exception {
- method @FlaggedApi("android.content.pm.cloud_compilation_pm") public int getCode();
- }
-
}
package android.hardware.usb {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 59327c8..7862a36 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2385,6 +2385,12 @@
method @NonNull public static byte[] digest(@NonNull java.io.InputStream, @NonNull String) throws java.io.IOException, java.security.NoSuchAlgorithmException;
}
+ public class Handler {
+ method @FlaggedApi("android.os.mainline_vcn_platform_api") public final boolean hasMessagesOrCallbacks();
+ method @FlaggedApi("android.os.mainline_vcn_platform_api") public final void removeCallbacksAndEqualMessages(@Nullable Object);
+ method @FlaggedApi("android.os.mainline_vcn_platform_api") public final void removeEqualMessages(int, @Nullable Object);
+ }
+
public class IpcDataCache<Query, Result> extends android.app.PropertyInvalidatedCache<Query,Result> {
ctor public IpcDataCache(int, @NonNull String, @NonNull String, @NonNull String, @NonNull android.os.IpcDataCache.QueryHandler<Query,Result>);
method public static void disableForCurrentProcess(@NonNull String);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 759d191..fbcefa3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3116,16 +3116,6 @@
public static final long MAXIMUM_VERIFICATION_TIMEOUT = 60*60*1000;
/**
- * As the generated feature count is useful for classes that may not be compiled in the same
- * annotation processing unit as PackageManager, we redeclare it here for visibility.
- *
- * @hide
- */
- @VisibleForTesting
- public static final int SDK_FEATURE_COUNT =
- com.android.internal.pm.SystemFeaturesMetadata.SDK_FEATURE_COUNT;
-
- /**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device's
* audio pipeline is low-latency, more suitable for audio applications sensitive to delays or
* lag in sound input or output.
@@ -11863,11 +11853,8 @@
* file.
*
* @throws SigningInfoException if the verification fails
- *
- * @hide
*/
@FlaggedApi(android.content.pm.Flags.FLAG_CLOUD_COMPILATION_PM)
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static @NonNull SigningInfo getVerifiedSigningInfo(@NonNull String path,
@AppSigningSchemeVersion int minAppSigningSchemeVersion) throws SigningInfoException {
ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
@@ -11879,4 +11866,28 @@
}
return new SigningInfo(result.getResult());
}
+
+ /**
+ * As the generated feature count is useful for classes that may not be compiled in the same
+ * annotation processing unit as PackageManager, we redeclare it here for visibility.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static final int SDK_FEATURE_COUNT =
+ com.android.internal.pm.SystemFeaturesMetadata.SDK_FEATURE_COUNT;
+
+ /**
+ * Returns a stable index for PackageManager-defined features.
+ *
+ * <p> Similar to {@link #SDK_FEATURE_COUNT}, we redeclare this utility method generated by the
+ * annotation processor for internal visibility.
+ *
+ * @return index in [0, {@link #SDK_FEATURECOUNT}) for PackageManager-defined features, else -1.
+ * @hide
+ */
+ @VisibleForTesting
+ public static int maybeGetSdkFeatureIndex(String featureName) {
+ return com.android.internal.pm.SystemFeaturesMetadata.maybeGetSdkFeatureIndex(featureName);
+ }
}
diff --git a/core/java/android/content/pm/SigningInfo.java b/core/java/android/content/pm/SigningInfo.java
index e4fbd1f..21bbb0a 100644
--- a/core/java/android/content/pm/SigningInfo.java
+++ b/core/java/android/content/pm/SigningInfo.java
@@ -22,7 +22,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
import android.content.pm.SigningDetails.SignatureSchemeVersion;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,41 +39,29 @@
/**
* JAR signing (v1 scheme).
* See https://source.android.com/docs/security/features/apksigning#v1.
- *
- * @hide
*/
@FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM)
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int VERSION_JAR = SignatureSchemeVersion.JAR;
/**
* APK signature scheme v2.
* See https://source.android.com/docs/security/features/apksigning/v2.
- *
- * @hide
*/
@FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM)
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int VERSION_SIGNING_BLOCK_V2 = SignatureSchemeVersion.SIGNING_BLOCK_V2;
/**
* APK signature scheme v3.
* See https://source.android.com/docs/security/features/apksigning/v3.
- *
- * @hide
*/
@FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM)
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int VERSION_SIGNING_BLOCK_V3 = SignatureSchemeVersion.SIGNING_BLOCK_V3;
/**
* APK signature scheme v4.
* See https://source.android.com/docs/security/features/apksigning/v4.
- *
- * @hide
*/
@FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM)
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int VERSION_SIGNING_BLOCK_V4 = SignatureSchemeVersion.SIGNING_BLOCK_V4;
/** @hide */
@@ -255,11 +242,8 @@
/**
* Returns true if the signing certificates in this and other match exactly.
- *
- * @hide
*/
@FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM)
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public boolean signersMatchExactly(@NonNull SigningInfo other) {
return mSigningDetails.signaturesMatchExactly(other.mSigningDetails);
}
diff --git a/core/java/android/content/pm/SigningInfoException.java b/core/java/android/content/pm/SigningInfoException.java
index a81e07e..2fd1bfb 100644
--- a/core/java/android/content/pm/SigningInfoException.java
+++ b/core/java/android/content/pm/SigningInfoException.java
@@ -19,17 +19,13 @@
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SystemApi;
/**
* Indicates an error when verifying the
* <a href="https://source.android.com/docs/security/features/apksigning">app signing</a>
* information.
- *
- * @hide
*/
@FlaggedApi(Flags.FLAG_CLOUD_COMPILATION_PM)
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public class SigningInfoException extends Exception {
private final int mCode;
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 901326d..2b8780c 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -149,6 +149,13 @@
}
flag {
+ name: "cache_sdk_system_features"
+ namespace: "system_performance"
+ description: "Feature flag to enable optimized cache for SDK-defined system feature lookups."
+ bug: "375000483"
+}
+
+flag {
name: "provide_info_of_apk_in_apex"
is_exported: true
namespace: "package_manager_service"
diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig
index f7dc790..a30cd5c 100644
--- a/core/java/android/net/flags.aconfig
+++ b/core/java/android/net/flags.aconfig
@@ -28,3 +28,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "mdns_improvement_for_25q2"
+ is_exported: true
+ namespace: "android_core_networking"
+ description: "Flag for MDNS quality, reliability and performance improvement in 25Q2"
+ bug: "373270045"
+}
diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java
index d0828c3..eaecd34 100644
--- a/core/java/android/os/Handler.java
+++ b/core/java/android/os/Handler.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.util.Log;
import android.util.Printer;
@@ -839,6 +840,7 @@
*@hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
@FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API)
public final void removeEqualMessages(int what, @Nullable Object object) {
mQueue.removeEqualMessages(this, what, disallowNullArgumentIfShared(object));
@@ -872,6 +874,7 @@
*@hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
@FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API)
public final void removeCallbacksAndEqualMessages(@Nullable Object token) {
mQueue.removeCallbacksAndEqualMessages(this, disallowNullArgumentIfShared(token));
@@ -889,6 +892,7 @@
* @hide
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @TestApi
@FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API)
public final boolean hasMessagesOrCallbacks() {
return mQueue.hasMessages(this);
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index ddf2b61..0125905 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -332,16 +332,55 @@
return -1;
}
+ private static int getThreadGroup() {
+ int threadGroup = Process.THREAD_GROUP_DEFAULT;
+
+ if (!Process.isIsolated()) {
+ threadGroup = Process.getProcessGroup(Process.myTid());
+ }
+ return threadGroup;
+ }
+
+ private static String threadGroupToString(int threadGroup) {
+ switch (threadGroup) {
+ case Process.THREAD_GROUP_BACKGROUND:
+ return "BACKGROUND";
+ case Process.THREAD_GROUP_FOREGROUND:
+ return "FOREGROUND";
+ case Process.THREAD_GROUP_SYSTEM:
+ return "SYSTEM";
+ case Process.THREAD_GROUP_AUDIO_APP:
+ return "AUDIO_APP";
+ case Process.THREAD_GROUP_AUDIO_SYS:
+ return "AUDIO_SYS";
+ case Process.THREAD_GROUP_TOP_APP:
+ return "TOP_APP";
+ case Process.THREAD_GROUP_RT_APP:
+ return "RT_APP";
+ case Process.THREAD_GROUP_RESTRICTED:
+ return "RESTRICTED";
+ default:
+ return "UNKNOWN";
+ }
+ }
+
private static boolean showSlowLog(long threshold, long measureStart, long measureEnd,
String what, Message msg) {
final long actualTime = measureEnd - measureStart;
if (actualTime < threshold) {
return false;
}
+
+ String name = Process.myProcessName();
+ String threadGroup = threadGroupToString(getThreadGroup());
+ boolean isMain = myLooper() == getMainLooper();
+
// For slow delivery, the current message isn't really important, but log it anyway.
Slog.w(TAG, "Slow " + what + " took " + actualTime + "ms "
- + Thread.currentThread().getName() + " h="
- + msg.target.getClass().getName() + " c=" + msg.callback + " m=" + msg.what);
+ + Thread.currentThread().getName() + " app=" + name
+ + " main=" + isMain + " group=" + threadGroup
+ + " h=" + msg.target.getClass().getName() + " c=" + msg.callback
+ + " m=" + msg.what);
return true;
}
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 8d35338..f3bb514 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -115,13 +115,20 @@
# Performance
per-file IpcDataCache.java = file:/PERFORMANCE_OWNERS
+# Processes, threads, and scheduling
+per-file Process.java = file:/PERFORMANCE_OWNERS
+
# Memory
per-file OomKillRecord.java = file:/MEMORY_OWNERS
# MessageQueue and related classes
per-file MessageQueue.java = mfasheh@google.com, shayba@google.com
per-file Message.java = mfasheh@google.com, shayba@google.com
+per-file Looper.java = mfasheh@google.com, shayba@google.com
per-file TestLooperManager.java = mfasheh@google.com, shayba@google.com
+per-file Handler.java = mfasheh@google.com, shayba@google.com
+per-file HandlerThread.java = mfasheh@google.com, shayba@google.com
+per-file HandlerExecutor.java = mfasheh@google.com, shayba@google.com
# Stats
per-file IStatsBootstrapAtomService.aidl = file:/services/core/java/com/android/server/stats/OWNERS
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 851953a..80a8dbe 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -560,10 +560,9 @@
* Foreground thread group - All threads in
* this group are scheduled with a normal share of the CPU.
* Value is same as constant SP_FOREGROUND of enum SchedPolicy.
- * Not used at this level.
* @hide
**/
- private static final int THREAD_GROUP_FOREGROUND = 1;
+ public static final int THREAD_GROUP_FOREGROUND = 1;
/**
* System thread group.
@@ -1316,19 +1315,6 @@
}
/**
- * Adjust the swappiness level for a process.
- *
- * @param pid The process identifier to set.
- * @param is_increased Whether swappiness should be increased or default.
- *
- * @return Returns true if the underlying system supports this
- * feature, else false.
- *
- * {@hide}
- */
- public static final native boolean setSwappiness(int pid, boolean is_increased);
-
- /**
* Change this process's argv[0] parameter. This can be useful to show
* more descriptive information in things like the 'ps' command.
*
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 49b696d..7ea521e 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -50,7 +50,8 @@
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
- mServiceManager = IServiceManager.Stub.asInterface(this.getNativeServiceManager());
+ mServiceManager = IServiceManager.Stub.asInterface(
+ Binder.allowBlocking(this.getNativeServiceManager()));
}
public IBinder asBinder() {
diff --git a/core/java/android/os/health/OWNERS b/core/java/android/os/health/OWNERS
index 6045344..26fc8fa 100644
--- a/core/java/android/os/health/OWNERS
+++ b/core/java/android/os/health/OWNERS
@@ -2,3 +2,6 @@
dplotnikov@google.com
mwachens@google.com
+
+# for headroom API only
+xwxw@google.com
\ No newline at end of file
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 6ea462e..71c9a2a 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -675,7 +675,7 @@
* @return true if a and b are equal
*/
@android.ravenwood.annotation.RavenwoodKeep
- public static boolean equals(CharSequence a, CharSequence b) {
+ public static boolean equals(@Nullable CharSequence a, @Nullable CharSequence b) {
if (a == b) return true;
int length;
if (a != null && b != null && (length = a.length()) == b.length()) {
diff --git a/core/java/com/android/internal/app/NfcResolverActivity.java b/core/java/com/android/internal/app/NfcResolverActivity.java
index 78427fe..f15dbd6 100644
--- a/core/java/com/android/internal/app/NfcResolverActivity.java
+++ b/core/java/com/android/internal/app/NfcResolverActivity.java
@@ -34,13 +34,13 @@
@Override
@SuppressWarnings("MissingSuperCall") // Called indirectly via `super_onCreate()`.
protected void onCreate(Bundle savedInstanceState) {
- if (!enableNfcMainline()) {
+ Intent intent = getIntent();
+ if (!enableNfcMainline() || intent.getExtras() == null) {
super_onCreate(savedInstanceState);
finish();
return;
}
- Intent intent = getIntent();
Intent target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent.class);
ArrayList<ResolveInfo> rList =
intent.getParcelableArrayListExtra(
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 19c6f51..9bd5237 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1326,7 +1326,7 @@
try {
getLockSettings().registerStrongAuthTracker(strongAuthTracker.getStub());
} catch (RemoteException e) {
- throw new RuntimeException("Could not register StrongAuthTracker");
+ e.rethrowFromSystemServer();
}
}
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 4369cb0..22d5ab8 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -584,32 +584,6 @@
return pri;
}
-jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz,
- jint pid, jboolean is_increased)
-{
- char text[64];
-
- if (is_increased) {
- strcpy(text, "/sys/fs/cgroup/memory/sw/tasks");
- } else {
- strcpy(text, "/sys/fs/cgroup/memory/tasks");
- }
-
- struct stat st;
- if (stat(text, &st) || !S_ISREG(st.st_mode)) {
- return false;
- }
-
- int fd = open(text, O_WRONLY | O_CLOEXEC);
- if (fd >= 0) {
- sprintf(text, "%" PRId32, pid);
- write(fd, text, strlen(text));
- close(fd);
- }
-
- return true;
-}
-
void android_os_Process_setArgV0(JNIEnv* env, jobject clazz, jstring name)
{
if (name == NULL) {
@@ -1392,7 +1366,6 @@
{"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup},
{"createProcessGroup", "(II)I", (void*)android_os_Process_createProcessGroup},
{"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores},
- {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
{"setArgV0Native", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
{"setUid", "(I)I", (void*)android_os_Process_setUid},
{"setGid", "(I)I", (void*)android_os_Process_setGid},
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp
index 76ead2a..48c92c8 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.cpp
+++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp
@@ -21,8 +21,6 @@
#include <android-base/file.h>
#include <android-base/hex.h>
#include <android-base/unique_fd.h>
-#include <bionic/macros.h>
-#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <linux/fs.h>
@@ -48,8 +46,8 @@
return false;
}
- start = align_up(start, blockSize);
- end = align_down(end, blockSize);
+ start = __builtin_align_up(start, blockSize);
+ end = __builtin_align_down(end, blockSize);
uint64_t alignedLength;
if (__builtin_sub_overflow(end, start, &alignedLength)) {
@@ -67,7 +65,7 @@
int result =
fallocate(fd.get(), FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, start, alignedLength);
if (result < 0) {
- ALOGE("fallocate failed to punch hole, error:%d", errno);
+ ALOGE("fallocate failed to punch hole: %m");
return false;
}
@@ -78,7 +76,7 @@
const std::vector<Elf64_Phdr> &programHeaders) {
struct stat64 beforePunch;
if (int result = lstat64(filePath, &beforePunch); result != 0) {
- ALOGE("lstat64 failed for filePath %s, error:%d", filePath, errno);
+ ALOGE("lstat64 failed for filePath %s: %m", filePath);
return false;
}
@@ -190,7 +188,7 @@
IF_ALOGD() {
struct stat64 afterPunch;
if (int result = lstat64(filePath, &afterPunch); result != 0) {
- ALOGD("lstat64 failed for filePath %s, error:%d", filePath, errno);
+ ALOGD("lstat64 failed for filePath %s: %m", filePath);
return false;
}
ALOGD("Size after punching holes st_blocks: %" PRIu64 ", st_blksize: %" PRIu64
@@ -269,7 +267,7 @@
struct stat64 beforePunch;
if (int result = lstat64(filePath, &beforePunch); result != 0) {
- ALOGE("lstat64 failed for filePath %s, error:%d", filePath, errno);
+ ALOGE("lstat64 failed for filePath %s: %m", filePath);
return false;
}
@@ -348,7 +346,7 @@
IF_ALOGD() {
struct stat64 afterPunch;
if (int result = lstat64(filePath, &afterPunch); result != 0) {
- ALOGD("lstat64 failed for filePath %s, error:%d", filePath, errno);
+ ALOGD("lstat64 failed for filePath %s: %m", filePath);
return false;
}
ALOGD("punchHolesInApk:: Size after punching holes st_blocks: %" PRIu64
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index aeaeeca..8c7b335 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -88,8 +88,8 @@
#include "nativebridge/native_bridge.h"
#if defined(__BIONIC__)
+#include <android/dlext_private.h>
extern "C" void android_reset_stack_guards();
-extern "C" void android_set_16kb_appcompat_mode(bool enable_app_compat);
#endif
namespace {
diff --git a/framework-jarjar-rules.txt b/framework-jarjar-rules.txt
index 087378b..3da69e8 100644
--- a/framework-jarjar-rules.txt
+++ b/framework-jarjar-rules.txt
@@ -10,3 +10,6 @@
# For Perfetto proto dependencies
rule perfetto.protos.** android.internal.perfetto.protos.@1
+
+# For aconfig storage classes
+rule android.aconfig.storage.** android.internal.aconfig.storage.@1
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 4287daa..4f22c14 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2871,7 +2871,8 @@
mSplitLayout.update(startTransaction, false /* resetImePosition */);
}
- if (mMixedHandler.isEnteringPip(change, transitType)) {
+ if (mMixedHandler.isEnteringPip(change, transitType)
+ && getSplitItemStage(change.getLastParent()) != STAGE_TYPE_UNDEFINED) {
pipChange = change;
}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index fc184fe..8419ce7 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -1149,9 +1149,9 @@
static jobject getJavaResources(
JNIEnv *env,
- const std::vector<MediaCodec::InstanceResourceInfo>& resources) {
+ const std::vector<InstanceResourceInfo>& resources) {
jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId);
- for (const MediaCodec::InstanceResourceInfo& res : resources) {
+ for (const InstanceResourceInfo& res : resources) {
ScopedLocalRef<jobject> object{env, env->NewObject(
gInstanceResourceInfo.clazz, gInstanceResourceInfo.ctorId)};
ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())};
@@ -1169,7 +1169,7 @@
}
status_t JMediaCodec::getRequiredResources(JNIEnv *env, jobject *resourcesObj) {
- std::vector<MediaCodec::InstanceResourceInfo> resources;
+ std::vector<InstanceResourceInfo> resources;
status_t status = mCodec->getRequiredResources(resources);
if (status != OK) {
return status;
@@ -3615,9 +3615,9 @@
static jobject getJavaResources(
JNIEnv *env,
- const std::vector<MediaCodec::GlobalResourceInfo>& resources) {
+ const std::vector<GlobalResourceInfo>& resources) {
jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId);
- for (const MediaCodec::GlobalResourceInfo& res : resources) {
+ for (const GlobalResourceInfo& res : resources) {
ScopedLocalRef<jobject> object{env, env->NewObject(
gGlobalResourceInfo.clazz, gGlobalResourceInfo.ctorId)};
ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())};
@@ -3633,7 +3633,7 @@
static jobject android_media_MediaCodec_getGloballyAvailableResources(
JNIEnv *env, jobject thiz) {
(void)thiz;
- std::vector<MediaCodec::GlobalResourceInfo> resources;
+ std::vector<GlobalResourceInfo> resources;
status_t status = MediaCodec::getGloballyAvailableResources(resources);
if (status != OK) {
if (status == ERROR_UNSUPPORTED) {
diff --git a/nfc/Android.bp b/nfc/Android.bp
index abe0ab7..c33665a 100644
--- a/nfc/Android.bp
+++ b/nfc/Android.bp
@@ -56,7 +56,7 @@
],
defaults: ["framework-module-defaults"],
sdk_version: "module_current",
- min_sdk_version: "current",
+ min_sdk_version: "35", // Make it 36 once available.
installable: true,
optimize: {
enabled: false,
@@ -71,6 +71,7 @@
"//cts/hostsidetests/multidevices/nfc:__subpackages__",
"//cts/tests/tests/nfc",
"//packages/apps/Nfc:__subpackages__",
+ "//packages/modules/Nfc:__subpackages__",
],
jarjar_rules: ":nfc-jarjar-rules",
lint: {
diff --git a/nfc/OWNERS b/nfc/OWNERS
index 35e9713..f46dccd 100644
--- a/nfc/OWNERS
+++ b/nfc/OWNERS
@@ -1,2 +1,2 @@
# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS
+include platform/packages/apps/Nfc:/OWNERS
\ No newline at end of file
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index 0ee81cb..c8c479a 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -211,7 +211,7 @@
method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
method @FlaggedApi("android.nfc.enable_card_emulation_euicc") public boolean isEuiccSupported();
method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
- method @FlaggedApi("android.nfc.nfc_event_listener") public void registerNfcEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.cardemulation.CardEmulation.NfcEventListener);
+ method @FlaggedApi("android.nfc.nfc_event_listener") public void registerNfcEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.cardemulation.CardEmulation.NfcEventCallback);
method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean);
method @FlaggedApi("android.nfc.nfc_read_polling_loop") public boolean registerPollingLoopPatternFilterForService(@NonNull android.content.ComponentName, @NonNull String, boolean);
method public boolean removeAidsForService(android.content.ComponentName, String);
@@ -221,7 +221,7 @@
method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setShouldDefaultToObserveModeForService(@NonNull android.content.ComponentName, boolean);
method public boolean supportsAidPrefixRegistration();
- method @FlaggedApi("android.nfc.nfc_event_listener") public void unregisterNfcEventListener(@NonNull android.nfc.cardemulation.CardEmulation.NfcEventListener);
+ method @FlaggedApi("android.nfc.nfc_event_listener") public void unregisterNfcEventCallback(@NonNull android.nfc.cardemulation.CardEmulation.NfcEventCallback);
method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
method public boolean unsetPreferredService(android.app.Activity);
field @Deprecated public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
@@ -244,7 +244,7 @@
field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
}
- @FlaggedApi("android.nfc.nfc_event_listener") public static interface CardEmulation.NfcEventListener {
+ @FlaggedApi("android.nfc.nfc_event_listener") public static interface CardEmulation.NfcEventCallback {
method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidConflictOccurred(@NonNull String);
method @FlaggedApi("android.nfc.nfc_event_listener") public default void onAidNotRouted(@NonNull String);
method @FlaggedApi("android.nfc.nfc_event_listener") public default void onInternalErrorReported(int);
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
index bb9fe95..00ceaa9 100644
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -17,7 +17,7 @@
package android.nfc;
import android.content.ComponentName;
-import android.nfc.INfcEventListener;
+import android.nfc.INfcEventCallback;
import android.nfc.cardemulation.AidGroup;
import android.nfc.cardemulation.ApduServiceInfo;
@@ -60,6 +60,6 @@
List<String> getRoutingStatus();
void overwriteRoutingTable(int userHandle, String emptyAid, String protocol, String tech, String sc);
- void registerNfcEventListener(in INfcEventListener listener);
- void unregisterNfcEventListener(in INfcEventListener listener);
+ void registerNfcEventCallback(in INfcEventCallback listener);
+ void unregisterNfcEventCallback(in INfcEventCallback listener);
}
diff --git a/nfc/java/android/nfc/INfcEventListener.aidl b/nfc/java/android/nfc/INfcEventCallback.aidl
similarity index 92%
rename from nfc/java/android/nfc/INfcEventListener.aidl
rename to nfc/java/android/nfc/INfcEventCallback.aidl
index 774d8f8..af1fa2fb 100644
--- a/nfc/java/android/nfc/INfcEventListener.aidl
+++ b/nfc/java/android/nfc/INfcEventCallback.aidl
@@ -5,7 +5,7 @@
/**
* @hide
*/
-oneway interface INfcEventListener {
+oneway interface INfcEventCallback {
void onPreferredServiceChanged(in ComponentNameAndUser ComponentNameAndUser);
void onObserveModeStateChanged(boolean isEnabled);
void onAidConflictOccurred(in String aid);
diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java
index 89ce423..63397c2 100644
--- a/nfc/java/android/nfc/NfcAdapter.java
+++ b/nfc/java/android/nfc/NfcAdapter.java
@@ -1789,6 +1789,11 @@
* @param listenTechnology Flags indicating listen technologies.
* @throws UnsupportedOperationException if FEATURE_NFC,
* FEATURE_NFC_HOST_CARD_EMULATION, FEATURE_NFC_HOST_CARD_EMULATION_NFCF are unavailable.
+ *
+ * NOTE: This API overrides all technology flags regardless of the current device state,
+ * it is incompatible with enableReaderMode() API and the others that either update
+ * or assume any techlology flag set by the OS.
+ * Please use with care.
*/
@FlaggedApi(Flags.FLAG_ENABLE_NFC_SET_DISCOVERY_TECH)
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index e0bc15f..fee9c5b 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -39,7 +39,7 @@
import android.nfc.Constants;
import android.nfc.Flags;
import android.nfc.INfcCardEmulation;
-import android.nfc.INfcEventListener;
+import android.nfc.INfcEventCallback;
import android.nfc.NfcAdapter;
import android.os.Build;
import android.os.RemoteException;
@@ -1304,7 +1304,7 @@
/** Listener for preferred service state changes. */
@FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
- public interface NfcEventListener {
+ public interface NfcEventCallback {
/**
* This method is called when this package gains or loses preferred Nfc service status,
* either the Default Wallet Role holder (see {@link
@@ -1327,7 +1327,10 @@
/**
* This method is called when an AID conflict is detected during an NFC transaction. This
- * can happen when multiple services are registered for the same AID.
+ * can happen when multiple services are registered for the same AID. If your service is
+ * registered for this AID you may want to instruct users to bring your app to the
+ * foreground and ensure you call {@link #setPreferredService(Activity, ComponentName)}
+ * to ensure the transaction is routed to your service.
*
* @param aid The AID that is in conflict
*/
@@ -1377,10 +1380,10 @@
default void onInternalErrorReported(@NfcInternalErrorType int errorType) {}
}
- private final ArrayMap<NfcEventListener, Executor> mNfcEventListeners = new ArrayMap<>();
+ private final ArrayMap<NfcEventCallback, Executor> mNfcEventCallbacks = new ArrayMap<>();
- final INfcEventListener mINfcEventListener =
- new INfcEventListener.Stub() {
+ final INfcEventCallback mINfcEventCallback =
+ new INfcEventCallback.Stub() {
public void onPreferredServiceChanged(ComponentNameAndUser componentNameAndUser) {
if (!android.nfc.Flags.nfcEventListener()) {
return;
@@ -1440,12 +1443,12 @@
}
interface ListenerCall {
- void invoke(NfcEventListener listener);
+ void invoke(NfcEventCallback listener);
}
private void callListeners(ListenerCall listenerCall) {
- synchronized (mNfcEventListeners) {
- mNfcEventListeners.forEach(
+ synchronized (mNfcEventCallbacks) {
+ mNfcEventCallbacks.forEach(
(listener, executor) -> {
executor.execute(() -> listenerCall.invoke(listener));
});
@@ -1460,34 +1463,34 @@
* @param listener The listener to register
*/
@FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
- public void registerNfcEventListener(
- @NonNull @CallbackExecutor Executor executor, @NonNull NfcEventListener listener) {
+ public void registerNfcEventCallback(
+ @NonNull @CallbackExecutor Executor executor, @NonNull NfcEventCallback listener) {
if (!android.nfc.Flags.nfcEventListener()) {
return;
}
- synchronized (mNfcEventListeners) {
- mNfcEventListeners.put(listener, executor);
- if (mNfcEventListeners.size() == 1) {
- callService(() -> sService.registerNfcEventListener(mINfcEventListener));
+ synchronized (mNfcEventCallbacks) {
+ mNfcEventCallbacks.put(listener, executor);
+ if (mNfcEventCallbacks.size() == 1) {
+ callService(() -> sService.registerNfcEventCallback(mINfcEventCallback));
}
}
}
/**
* Unregister a preferred service listener that was previously registered with {@link
- * #registerNfcEventListener(Executor, NfcEventListener)}
+ * #registerNfcEventCallback(Executor, NfcEventCallback)}
*
* @param listener The previously registered listener to unregister
*/
@FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
- public void unregisterNfcEventListener(@NonNull NfcEventListener listener) {
+ public void unregisterNfcEventCallback(@NonNull NfcEventCallback listener) {
if (!android.nfc.Flags.nfcEventListener()) {
return;
}
- synchronized (mNfcEventListeners) {
- mNfcEventListeners.remove(listener);
- if (mNfcEventListeners.size() == 0) {
- callService(() -> sService.unregisterNfcEventListener(mINfcEventListener));
+ synchronized (mNfcEventCallbacks) {
+ mNfcEventCallbacks.remove(listener);
+ if (mNfcEventCallbacks.size() == 0) {
+ callService(() -> sService.unregisterNfcEventCallback(mINfcEventCallback));
}
}
}
diff --git a/nfc/java/android/nfc/cardemulation/HostApduService.java b/nfc/java/android/nfc/cardemulation/HostApduService.java
index db1f6a2..fbf2203 100644
--- a/nfc/java/android/nfc/cardemulation/HostApduService.java
+++ b/nfc/java/android/nfc/cardemulation/HostApduService.java
@@ -289,7 +289,7 @@
try {
mNfcService.send(responseMsg);
} catch (RemoteException e) {
- Log.e("TAG", "Response not sent; RemoteException calling into " +
+ Log.e(TAG, "Response not sent; RemoteException calling into " +
"NfcService.");
}
}
diff --git a/nfc/java/android/nfc/cardemulation/OWNERS b/nfc/java/android/nfc/cardemulation/OWNERS
deleted file mode 100644
index 35e9713..0000000
--- a/nfc/java/android/nfc/cardemulation/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS
diff --git a/nfc/java/android/nfc/dta/OWNERS b/nfc/java/android/nfc/dta/OWNERS
deleted file mode 100644
index 35e9713..0000000
--- a/nfc/java/android/nfc/dta/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS
diff --git a/nfc/java/android/nfc/tech/OWNERS b/nfc/java/android/nfc/tech/OWNERS
deleted file mode 100644
index 35e9713..0000000
--- a/nfc/java/android/nfc/tech/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS
diff --git a/nfc/tests/src/android/nfc/NfcAntennaInfoTest.java b/nfc/tests/src/android/nfc/NfcAntennaInfoTest.java
new file mode 100644
index 0000000..c24816d
--- /dev/null
+++ b/nfc/tests/src/android/nfc/NfcAntennaInfoTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NfcAntennaInfoTest {
+ private NfcAntennaInfo mNfcAntennaInfo;
+
+
+ @Before
+ public void setUp() {
+ AvailableNfcAntenna availableNfcAntenna = mock(AvailableNfcAntenna.class);
+ List<AvailableNfcAntenna> antennas = new ArrayList<>();
+ antennas.add(availableNfcAntenna);
+ mNfcAntennaInfo = new NfcAntennaInfo(1, 1, false, antennas);
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void testGetDeviceHeight() {
+ int height = mNfcAntennaInfo.getDeviceHeight();
+ assertThat(height).isEqualTo(1);
+ }
+
+ @Test
+ public void testGetDeviceWidth() {
+ int width = mNfcAntennaInfo.getDeviceWidth();
+ assertThat(width).isEqualTo(1);
+ }
+
+ @Test
+ public void testIsDeviceFoldable() {
+ boolean foldable = mNfcAntennaInfo.isDeviceFoldable();
+ assertThat(foldable).isFalse();
+ }
+
+ @Test
+ public void testGetAvailableNfcAntennas() {
+ List<AvailableNfcAntenna> antennas = mNfcAntennaInfo.getAvailableNfcAntennas();
+ assertThat(antennas).isNotNull();
+ assertThat(antennas.size()).isEqualTo(1);
+ }
+
+}
diff --git a/nfc/tests/src/android/nfc/cardemulation/AidGroupTest.java b/nfc/tests/src/android/nfc/cardemulation/AidGroupTest.java
new file mode 100644
index 0000000..7e00102
--- /dev/null
+++ b/nfc/tests/src/android/nfc/cardemulation/AidGroupTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.cardemulation;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class AidGroupTest {
+ private AidGroup mAidGroup;
+
+ @Before
+ public void setUp() {
+ List<String> aids = new ArrayList<>();
+ aids.add("A0000000031010");
+ aids.add("A0000000041010");
+ aids.add("A0000000034710");
+ aids.add("A000000300");
+ mAidGroup = new AidGroup(aids, "payment");
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void testGetCategory() {
+ String category = mAidGroup.getCategory();
+ assertThat(category).isNotNull();
+ assertThat(category).isEqualTo("payment");
+ }
+
+ @Test
+ public void testGetAids() {
+ List<String> aids = mAidGroup.getAids();
+ assertThat(aids).isNotNull();
+ assertThat(aids.size()).isGreaterThan(0);
+ assertThat(aids.get(0)).isEqualTo("A0000000031010");
+ }
+
+ @Test
+ public void testWriteAsXml() throws IOException {
+ XmlSerializer out = mock(XmlSerializer.class);
+ mAidGroup.writeAsXml(out);
+ verify(out, atLeastOnce()).startTag(isNull(), anyString());
+ verify(out, atLeastOnce()).attribute(isNull(), anyString(), anyString());
+ verify(out, atLeastOnce()).endTag(isNull(), anyString());
+ }
+
+ @Test
+ public void testRightToParcel() {
+ Parcel parcel = mock(Parcel.class);
+ mAidGroup.writeToParcel(parcel, 0);
+ verify(parcel).writeString8(anyString());
+ verify(parcel).writeInt(anyInt());
+ verify(parcel).writeStringList(any());
+ }
+}
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
index c3ecff4..dd939bb 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -12,3 +12,7 @@
omakoto@google.com
michaelwr@google.com
ronish@google.com
+
+# Wear Bugreport Owners
+ranamouawi@google.com
+yashasvig@google.com
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index bcfd8f6..75156ba 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -236,6 +236,9 @@
/** Always keep remote bugreport files created in the last day. */
private static final long REMOTE_MIN_KEEP_AGE = DateUtils.DAY_IN_MILLIS;
+ /** Minimum delay for sending last update notification */
+ private static final int DELAY_NOTIFICATION_MS = 250;
+
private final Object mLock = new Object();
/** Managed bugreport info (keyed by id) */
@@ -849,6 +852,7 @@
Log.d(TAG, "Progress #" + info.id + ": " + percentageText);
}
info.lastProgress.set(progress);
+ info.lastUpdate.set(System.currentTimeMillis());
sendForegroundabledNotification(info.id, builder.build());
}
@@ -1368,6 +1372,16 @@
*/
private void sendBugreportNotification(BugreportInfo info, boolean takingScreenshot) {
+ final long lastUpdate = System.currentTimeMillis() - info.lastUpdate.longValue();
+ if (lastUpdate < DELAY_NOTIFICATION_MS) {
+ Log.d(TAG, "Delaying final notification for "
+ + (DELAY_NOTIFICATION_MS - lastUpdate) + " ms ");
+ mMainThreadHandler.postDelayed(() -> {
+ sendBugreportNotification(info, takingScreenshot);
+ }, DELAY_NOTIFICATION_MS - lastUpdate);
+ return;
+ }
+
// Since adding the details can take a while, do it before notifying user.
addDetailsToZipFile(info);
@@ -1388,6 +1402,7 @@
final Notification.Builder builder = newBaseNotification(mContext)
.setContentTitle(title)
.setTicker(title)
+ .setProgress(100 /* max value of progress percentage */, 100, false)
.setOnlyAlertOnce(false)
.setContentText(content);
@@ -2426,7 +2441,6 @@
}
}
info.progress.set(progress);
- info.lastUpdate.set(System.currentTimeMillis());
updateProgress(info);
}
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 050a370..7bda2ea 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -193,7 +193,7 @@
mService.mScreenshotDelaySec = SCREENSHOT_DELAY_SECONDS;
// Dup the fds which are passing to startBugreport function.
Mockito.doAnswer(invocation -> {
- final boolean isScreenshotRequested = invocation.getArgument(6);
+ final boolean isScreenshotRequested = invocation.getArgument(7);
if (isScreenshotRequested) {
mScreenshotFd = ParcelFileDescriptor.dup(invocation.getArgument(3));
}
@@ -250,7 +250,22 @@
mIDumpstateListener.onProgress(300);
assertProgressNotification(mProgressTitle, 99);
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId);
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId, 1);
+ assertActionSendMultiple(extras);
+
+ assertServiceNotRunning();
+ }
+
+ @Test
+ public void testStressProgress() throws Exception {
+ sendBugreportStarted();
+ waitForScreenshotButtonEnabled(true);
+
+ for (int i = 0; i <= 1000; i++) {
+ mIDumpstateListener.onProgress(i);
+ }
+ sendBugreportFinished();
+ Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 1);
assertActionSendMultiple(extras);
assertServiceNotRunning();
@@ -277,7 +292,7 @@
assertScreenshotButtonEnabled(false);
waitForScreenshotButtonEnabled(true);
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId);
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId, 2);
assertActionSendMultiple(extras, NO_NAME, NO_TITLE, NO_DESCRIPTION, 1);
assertServiceNotRunning();
@@ -294,7 +309,7 @@
// There's no indication in the UI about the screenshot finish, so just sleep like a baby...
sleep(SAFE_SCREENSHOT_DELAY * DateUtils.SECOND_IN_MILLIS);
- Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId);
+ Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 2);
assertActionSendMultiple(extras, NO_NAME, NO_TITLE, NO_DESCRIPTION, 1);
assertServiceNotRunning();
@@ -328,7 +343,7 @@
assertProgressNotification(NEW_NAME, 00.00f);
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE);
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE, 1);
assertActionSendMultiple(extras, NEW_NAME, TITLE, mDescription, 0);
assertServiceNotRunning();
@@ -363,7 +378,7 @@
assertProgressNotification(NEW_NAME, 00.00f);
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE);
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(TITLE, 1);
assertActionSendMultiple(extras, NEW_NAME, TITLE, mDescription, 0);
assertServiceNotRunning();
@@ -390,7 +405,7 @@
detailsUi.descField.setText(mDescription);
detailsUi.clickOk();
- Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId);
+ Bundle extras = sendBugreportFinishedAndGetSharedIntent(mBugreportId, 1);
assertActionSendMultiple(extras, NO_NAME, NO_TITLE, mDescription, 0);
assertServiceNotRunning();
@@ -441,7 +456,7 @@
detailsUi.clickOk();
// Finally, share bugreport.
- Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId);
+ Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 1);
assertActionSendMultiple(extras, NO_NAME, TITLE, mDescription, 0);
assertServiceNotRunning();
@@ -504,7 +519,7 @@
mUiBot.click(ok, "ok");
// Share the bugreport.
- mUiBot.chooseActivity(UI_NAME);
+ mUiBot.chooseActivity(UI_NAME, mContext, 1);
Bundle extras = mListener.getExtras();
assertActionSendMultiple(extras);
@@ -531,7 +546,7 @@
sendBugreportFinished();
killService();
assertServiceNotRunning();
- Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId);
+ Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 1);
assertActionSendMultiple(extras);
}
@@ -618,45 +633,49 @@
* Sends a "bugreport finished" event and waits for the result.
*
* @param id The bugreport id for finished notification string title substitution.
+ * @param count Number of files to be shared
* @return extras sent in the shared intent.
*/
- private Bundle sendBugreportFinishedAndGetSharedIntent(int id) throws Exception {
+ private Bundle sendBugreportFinishedAndGetSharedIntent(int id, int count) throws Exception {
sendBugreportFinished();
- return acceptBugreportAndGetSharedIntent(id);
+ return acceptBugreportAndGetSharedIntent(id, count);
}
/**
* Sends a "bugreport finished" event and waits for the result.
*
* @param notificationTitle The title of finished notification.
+ * @param count Number of files to be shared
* @return extras sent in the shared intent.
*/
- private Bundle sendBugreportFinishedAndGetSharedIntent(String notificationTitle)
+ private Bundle sendBugreportFinishedAndGetSharedIntent(String notificationTitle, int count)
throws Exception {
sendBugreportFinished();
- return acceptBugreportAndGetSharedIntent(notificationTitle);
+ return acceptBugreportAndGetSharedIntent(notificationTitle, count);
}
/**
* Accepts the notification to share the finished bugreport and waits for the result.
*
* @param id The bugreport id for finished notification string title substitution.
+ * @param count Number of files to be shared
* @return extras sent in the shared intent.
*/
- private Bundle acceptBugreportAndGetSharedIntent(int id) {
+ private Bundle acceptBugreportAndGetSharedIntent(int id, int count) {
final String notificationTitle = mContext.getString(R.string.bugreport_finished_title, id);
- return acceptBugreportAndGetSharedIntent(notificationTitle);
+ return acceptBugreportAndGetSharedIntent(notificationTitle, count);
}
/**
* Accepts the notification to share the finished bugreport and waits for the result.
*
* @param notificationTitle The title of finished notification.
+ * @param count Number of files to be shared
* @return extras sent in the shared intent.
*/
- private Bundle acceptBugreportAndGetSharedIntent(String notificationTitle) {
+ private Bundle acceptBugreportAndGetSharedIntent(String notificationTitle, int count) {
mUiBot.clickOnNotification(notificationTitle);
- mUiBot.chooseActivity(UI_NAME);
+ mUiBot.chooseActivity(UI_NAME, mContext, count);
return mListener.getExtras();
}
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index ce9f70d..60008a3 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -18,9 +18,12 @@
import android.app.Instrumentation;
import android.app.StatusBarManager;
+import android.content.Context;
+import android.content.res.Resources;
import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.Log;
+import android.util.PluralsMessageFormatter;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
@@ -34,7 +37,9 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* A helper class for UI-related testing tasks.
@@ -206,11 +211,26 @@
*
* @param name name of the activity as displayed in the UI (typically the value set by
* {@code android:label} in the manifest).
+ * @param context Context of the target application
+ * @param count Number of files to be shared
*/
- public void chooseActivity(String name) {
+ public void chooseActivity(String name, Context context, int count) {
// It uses an intent chooser now, so just getting the activity by text is enough...
- final String share = mInstrumentation.getContext().getString(
- com.android.internal.R.string.share);
+ Resources res = null;
+ try {
+ res = context.getPackageManager()
+ .getResourcesForApplication("com.android.intentresolver");
+ } catch (Exception e) {
+ assertNotNull("could not get resources for com.android.intentresolver", res);
+ }
+ /* Resource read is defined as a string which contains a plural
+ * which needs some formatting */
+ Map<String, Object> arguments = new HashMap<>();
+ arguments.put("count", count);
+ final String share = PluralsMessageFormatter.format(
+ res,
+ arguments,
+ res.getIdentifier("sharing_files", "string", "com.android.intentresolver"));
boolean gotIt = mDevice.wait(Until.hasObject(By.text(share)), mTimeout);
assertTrue("could not get share activity (" + share + ")", gotIt);
swipeUp();
diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml
index 42733a2..0c29bb4 100644
--- a/packages/SystemUI/res-product/values/strings.xml
+++ b/packages/SystemUI/res-product/values/strings.xml
@@ -179,6 +179,8 @@
<!-- Text informing the user that their media is now playing on this tablet device. [CHAR LIMIT=50] -->
<string name="media_transfer_playing_this_device" product="tablet">Playing on this tablet</string>
-
+ <!-- Message shown during shutdown when Find My Device with Dead Battery Finder is active [CHAR LIMIT=300] -->
+ <string name="finder_active" product="default">You can locate this phone with Find My Device even when powered off</string>
+ <string name="finder_active" product="tablet">You can locate this tablet with Find My Device even when powered off</string>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d51831b..261ffa0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2382,8 +2382,6 @@
<!-- Tuner string -->
<!-- Tuner string -->
- <!-- Message shown during shutdown when Find My Device with Dead Battery Finder is active [CHAR LIMIT=300] -->
- <string name="finder_active">You can locate this phone with Find My Device even when powered off</string>
<!-- Shutdown Progress Dialog. This is shown if the user chooses to power off the phone. [CHAR LIMIT=60] -->
<string name="shutdown_progress">Shutting down\u2026</string>
diff --git a/packages/Vcn/flags/Android.bp b/packages/Vcn/flags/Android.bp
index 3943c6f..8d09fdb 100644
--- a/packages/Vcn/flags/Android.bp
+++ b/packages/Vcn/flags/Android.bp
@@ -29,10 +29,24 @@
],
}
+// TODO: b/374174952 Remove this library when VCN modularization is done
java_aconfig_library {
name: "android.net.vcn.flags-aconfig-java-export",
aconfig_declarations: "android.net.vcn.flags-aconfig",
mode: "exported",
min_sdk_version: "35",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ apex_available: [
+ "//apex_available:platform",
+ ],
+}
+
+java_aconfig_library {
+ name: "android.net.vcn.flags-aconfig-java",
+ aconfig_declarations: "android.net.vcn.flags-aconfig",
+ min_sdk_version: "35",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ apex_available: [
+ "com.android.tethering",
+ ],
}
diff --git a/packages/Vcn/framework-b/Android.bp b/packages/Vcn/framework-b/Android.bp
index c312116..edb22c0 100644
--- a/packages/Vcn/framework-b/Android.bp
+++ b/packages/Vcn/framework-b/Android.bp
@@ -32,9 +32,9 @@
}
java_defaults {
- name: "framework-connectivity-b-defaults",
+ name: "framework-connectivity-b-defaults-base",
sdk_version: "module_current",
- min_sdk_version: "35", // TODO: Make it Android 25Q2 when this is included in mainline
+
defaults: ["framework-module-defaults"], // This is a boot jar
srcs: [
@@ -44,14 +44,10 @@
libs: [
"android.net.ipsec.ike.stubs.module_lib",
- "app-compat-annotations",
"framework-wifi.stubs.module_lib",
"unsupportedappusage",
],
- static_libs: [
- //TODO:375213246 Use a non-exported flag lib when VCN is in mainline
- "android.net.vcn.flags-aconfig-java-export",
- ],
+
aidl: {
include_dirs: [
// For connectivity-framework classes such as Network.aidl, NetworkCapabilities.aidl
@@ -60,16 +56,83 @@
},
}
+soong_config_module_type {
+ name: "framework_connectivity_b_defaults_soong_config",
+ module_type: "java_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "is_vcn_in_mainline",
+ ],
+ properties: [
+ "min_sdk_version",
+ "static_libs",
+ "apex_available",
+ ],
+}
+
+framework_connectivity_b_defaults_soong_config {
+ name: "framework-connectivity-b-defaults",
+ defaults: [
+ "framework-connectivity-b-defaults-base",
+ ],
+ soong_config_variables: {
+ is_vcn_in_mainline: {
+ //TODO: b/380155299 Make it Baklava when aidl tool can understand it
+ min_sdk_version: "current",
+ static_libs: ["android.net.vcn.flags-aconfig-java"],
+ apex_available: ["com.android.tethering"],
+
+ conditions_default: {
+ min_sdk_version: "35",
+ static_libs: ["android.net.vcn.flags-aconfig-java-export"],
+ apex_available: ["//apex_available:platform"],
+ },
+ },
+ },
+}
+
+soong_config_module_type {
+ name: "framework_connectivity_b_java_sdk_library_defaults_soong_config",
+ module_type: "java_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: [
+ "is_vcn_in_mainline",
+ ],
+ properties: [
+ "aconfig_declarations",
+ "jarjar_rules",
+ ],
+}
+
+framework_connectivity_b_java_sdk_library_defaults_soong_config {
+ name: "framework-connectivity-b-java-sdk-library-defaults",
+ soong_config_variables: {
+ is_vcn_in_mainline: {
+ aconfig_declarations: ["android.net.vcn.flags-aconfig-java"],
+
+ // TODO: b/375213246 Use the connectivity jarjar rule generator to create the
+ // jarjar rules. In the end state, use "framework-connectivity-jarjar-rules"
+ // after VCN code is moved to the Connectivity folder
+ jarjar_rules: "framework-vcn-jarjar-rules.txt",
+
+ conditions_default: {
+ aconfig_declarations: ["android.net.vcn.flags-aconfig-java-export"],
+
+ // Use "android.net.connectivity" as prefix would trigger
+ // "Hidden API flags are inconsistent" build error
+ jarjar_rules: "framework-vcn-jarjar-rules-platform.txt",
+ },
+ },
+ },
+}
+
java_sdk_library {
name: "framework-connectivity-b",
defaults: [
"framework-connectivity-b-defaults",
+ "framework-connectivity-b-java-sdk-library-defaults",
],
- //TODO: b/375213246 Use "framework-connectivity-jarjar-rules" when VCN is
- // in mainline
- jarjar_rules: "framework-vcn-jarjar-rules.txt",
-
permitted_packages: [
"android.net",
"android.net.vcn",
@@ -92,11 +155,6 @@
"framework-connectivity-pre-jarjar",
],
- aconfig_declarations: [
- //TODO:375213246 Use a non-exported flag lib when VCN is in mainline
- "android.net.vcn.flags-aconfig-java-export",
- ],
-
impl_library_visibility: [
// Using for test only
"//cts/tests/netlegacy22.api",
@@ -120,17 +178,13 @@
"//packages/modules/Wifi/service/tests/wifitests",
],
- apex_available: [
- // TODO: b/374174952 Remove it when VCN modularization is released
- "//apex_available:platform",
-
- "com.android.tethering",
- ],
+ visibility: ["//packages/modules/Connectivity:__subpackages__"],
}
java_library {
name: "framework-connectivity-b-pre-jarjar",
defaults: ["framework-connectivity-b-defaults"],
+ installable: false,
libs: [
"framework-connectivity-pre-jarjar",
],
diff --git a/packages/Vcn/framework-b/framework-vcn-jarjar-rules-platform.txt b/packages/Vcn/framework-b/framework-vcn-jarjar-rules-platform.txt
new file mode 100644
index 0000000..757043b
--- /dev/null
+++ b/packages/Vcn/framework-b/framework-vcn-jarjar-rules-platform.txt
@@ -0,0 +1,2 @@
+rule android.net.vcn.persistablebundleutils.** android.net.vcn.module.repackaged.persistablebundleutils.@1
+rule android.net.vcn.util.** android.net.vcn.module.repackaged.util.@1
\ No newline at end of file
diff --git a/packages/Vcn/framework-b/framework-vcn-jarjar-rules.txt b/packages/Vcn/framework-b/framework-vcn-jarjar-rules.txt
index 757043b..7e27b24 100644
--- a/packages/Vcn/framework-b/framework-vcn-jarjar-rules.txt
+++ b/packages/Vcn/framework-b/framework-vcn-jarjar-rules.txt
@@ -1,2 +1,2 @@
-rule android.net.vcn.persistablebundleutils.** android.net.vcn.module.repackaged.persistablebundleutils.@1
-rule android.net.vcn.util.** android.net.vcn.module.repackaged.util.@1
\ No newline at end of file
+rule android.net.vcn.persistablebundleutils.** android.net.connectivity.android.net.vcn.persistablebundleutils.@1
+rule android.net.vcn.util.** android.net.connectivity.android.net.vcn.util.@1
\ No newline at end of file
diff --git a/packages/Vcn/framework-b/src/android/net/ConnectivityFrameworkInitializerBaklava.java b/packages/Vcn/framework-b/src/android/net/ConnectivityFrameworkInitializerBaklava.java
index 1f0fa92..de22ca6 100644
--- a/packages/Vcn/framework-b/src/android/net/ConnectivityFrameworkInitializerBaklava.java
+++ b/packages/Vcn/framework-b/src/android/net/ConnectivityFrameworkInitializerBaklava.java
@@ -23,8 +23,6 @@
import android.annotation.SystemApi;
import android.app.SystemServiceRegistry;
import android.compat.Compatibility;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.vcn.IVcnManagementService;
@@ -40,17 +38,15 @@
@FlaggedApi(FLAG_MAINLINE_VCN_MODULE_API)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class ConnectivityFrameworkInitializerBaklava {
- /**
- * Starting with {@link VANILLA_ICE_CREAM}, Telephony feature flags (e.g. {@link
- * PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}) are being checked before returning managers
- * that depend on them. If the feature is missing, {@link Context#getSystemService} will return
- * null.
- *
- * <p>This change is specific to VcnManager.
- */
- @ChangeId
- @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
- private static final long ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN = 330902016;
+
+ // This is a copy of TelephonyFrameworkInitializer.ENABLE_CHECKING_TELEPHONY_FEATURES. This
+ // ChangeId will replace ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN to gate VcnManager
+ // feature flag enforcement.
+ // This replacement is safe because both ChangeIds have been enabled since Android V and serve
+ // the same purpose: enforcing telephony feature flag checks before using telephony-based
+ // features. This also simplifies VCN modularization by avoiding the need to handle different
+ // states, such as: SDK < B vs. SDK >= B; VCN in platform vs. VCN in the apex.
+ private static final long ENABLE_CHECKING_TELEPHONY_FEATURES = 330583731;
/**
* The corresponding vendor API for Android V
@@ -71,7 +67,7 @@
private static String getVcnFeatureDependency() {
// Check SDK version of the client app. Apps targeting pre-V SDK might
// have not checked for existence of these features.
- if (!Compatibility.isChangeEnabled(ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN)) {
+ if (!Compatibility.isChangeEnabled(ENABLE_CHECKING_TELEPHONY_FEATURES)) {
return null;
}
diff --git a/packages/Vcn/service-b/Android.bp b/packages/Vcn/service-b/Android.bp
index c1a1ee7..1370b06 100644
--- a/packages/Vcn/service-b/Android.bp
+++ b/packages/Vcn/service-b/Android.bp
@@ -32,11 +32,9 @@
visibility: ["//frameworks/base/services/core"],
}
-// Do not static include this lib in VCN because these files exist in
-// both service-connectivity.jar and framework.jar
-// TODO: b/374174952 After VCN moves to Connectivity/ and the modularization is done
-// this lib can be removed and "service-connectivity-b-pre-jarjar" can include
-// "service-connectivity-pre-jarjar"
+// TODO: b/374174952 This library is only used in "service-connectivity-b-platform"
+// After VCN moves to Connectivity/ and the modularization is done, this lib and
+// "service-connectivity-b-platform" can both be removed
java_library {
name: "connectivity-utils-service-vcn-internal",
sdk_version: "module_current",
@@ -48,30 +46,30 @@
"framework-annotations-lib",
"unsupportedappusage",
],
- visibility: [
- "//visibility:private",
- ],
- apex_available: [
- // TODO: b/374174952 Remove it when VCN modularization is released
- "//apex_available:platform",
+ visibility: ["//visibility:private"],
+}
- "com.android.tethering",
+filegroup {
+ name: "service-vcn-sources",
+ srcs: ["src/**/*.java"],
+ path: "src",
+ visibility: [
+ "//packages/modules/Connectivity/service-b",
],
}
-java_library {
- name: "service-connectivity-b-pre-jarjar",
- sdk_version: "system_server_current",
- min_sdk_version: "35", // TODO: Make it Android 25Q2 when this is included in mainline
+// This java_defaults will be used for "service-connectivity-b-platform" and
+// "service-connectivity-b-pre-jarjar"
+java_defaults {
+ name: "service-connectivity-b-pre-jarjar-defaults",
defaults: ["framework-system-server-module-defaults"], // This is a system server jar
srcs: [
- "src/**/*.java",
+ ":service-vcn-sources",
],
libs: [
"android.net.ipsec.ike.stubs.module_lib",
- "connectivity-utils-service-vcn-internal",
"framework-annotations-lib",
"framework-connectivity-pre-jarjar",
"framework-connectivity-t-pre-jarjar",
@@ -89,13 +87,30 @@
"modules-utils-handlerexecutor",
],
+ defaults_visibility: [
+ "//packages/modules/Connectivity/service-b",
+ ],
+}
+
+// This library is only used to be included into services.jar when the build system
+// flag RELEASE_MOVE_VCN_TO_MAINLINE is disabled. When the flag is enabled, a module
+// version of this library will be included in Tethering module
+java_library {
+ name: "service-connectivity-b-platform",
+ defaults: ["service-connectivity-b-pre-jarjar-defaults"],
+ static_libs: ["connectivity-utils-service-vcn-internal"],
+
+ sdk_version: "system_server_current",
+ min_sdk_version: "35",
+
+ // TODO (b/374174952 ): This file is for jarjaring files in
+ // "connectivity-utils-service-vcn-internal".
+ jarjar_rules: "service-vcn-platform-jarjar-rules.txt",
+
visibility: [
"//frameworks/base/services",
],
apex_available: [
- // TODO: b/374174952 Remove it when VCN modularization is released
"//apex_available:platform",
-
- "com.android.tethering",
],
}
diff --git a/packages/Vcn/service-b/service-vcn-platform-jarjar-rules.txt b/packages/Vcn/service-b/service-vcn-platform-jarjar-rules.txt
new file mode 100644
index 0000000..3630727
--- /dev/null
+++ b/packages/Vcn/service-b/service-vcn-platform-jarjar-rules.txt
@@ -0,0 +1,5 @@
+rule android.util.IndentingPrintWriter android.net.vcn.module.repackaged.android.util.IndentingPrintWriter
+rule android.util.LocalLog android.net.vcn.module.repackaged.android.util.LocalLog
+rule com.android.internal.util.IndentingPrintWriter android.net.vcn.module.repackaged.com.android.internal.util.IndentingPrintWriter
+rule com.android.internal.util.MessageUtils android.net.vcn.module.repackaged.com.android.internal.util.MessageUtils
+rule com.android.internal.util.WakeupMessage android.net.vcn.module.repackaged.com.android.internal.util.WakeupMessage
\ No newline at end of file
diff --git a/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java b/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java
index 02c8ce4..81c7edf 100644
--- a/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java
+++ b/packages/Vcn/service-b/src/com/android/server/ConnectivityServiceInitializerB.java
@@ -16,7 +16,9 @@
package com.android.server;
+import android.annotation.TargetApi;
import android.content.Context;
+import android.os.Build;
import android.util.Log;
import com.android.tools.r8.keepanno.annotations.KeepItemKind;
@@ -30,6 +32,8 @@
// Without this annotation, this class will be treated as unused class and be removed during build
// time.
@UsedByReflection(kind = KeepItemKind.CLASS_AND_METHODS)
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public final class ConnectivityServiceInitializerB extends SystemService {
private static final String TAG = ConnectivityServiceInitializerB.class.getSimpleName();
private final VcnManagementService mVcnManagementService;
diff --git a/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java b/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java
index 26db6a9..c9a99d7 100644
--- a/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java
+++ b/packages/Vcn/service-b/src/com/android/server/VcnManagementService.java
@@ -37,6 +37,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -164,6 +165,8 @@
* @hide
*/
// TODO(b/180451994): ensure all incoming + outgoing calls have a cleared calling identity
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
@NonNull private static final String CONTEXT_ATTRIBUTION_TAG = "VCN";
@@ -297,8 +300,10 @@
});
}
- // Package-visibility for SystemServer to create instances.
- static VcnManagementService create(@NonNull Context context) {
+ /** Called by ConnectivityServiceInitializerB to create instances. */
+ // VcnManagementService will be jarjared but ConnectivityServiceInitializerB will not. Thus this
+ // method needs to be public for ConnectivityServiceInitializerB to access
+ public static VcnManagementService create(@NonNull Context context) {
return new VcnManagementService(context, new Dependencies());
}
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java b/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java
index b448f75..b04e25d 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -22,12 +22,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.vcn.VcnManager;
import android.net.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
+import android.os.Build;
import android.os.Handler;
import android.os.ParcelUuid;
import android.os.PersistableBundle;
@@ -77,6 +79,8 @@
*
* @hide
*/
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class TelephonySubscriptionTracker extends BroadcastReceiver {
@NonNull private static final String TAG = TelephonySubscriptionTracker.class.getSimpleName();
private static final boolean LOG_DBG = false; // STOPSHIP if true
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java b/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java
index 2524d0e..369ef6a 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/Vcn.java
@@ -29,6 +29,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.NetworkCapabilities;
@@ -39,6 +40,7 @@
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnManager.VcnErrorCode;
import android.net.vcn.util.LogUtils;
+import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
@@ -75,6 +77,8 @@
*
* @hide
*/
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class Vcn extends Handler {
private static final String TAG = Vcn.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java b/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java
index e50fc3a..300b80f 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/VcnGatewayConnection.java
@@ -37,6 +37,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
@@ -82,6 +84,7 @@
import android.net.vcn.util.MtuUtils;
import android.net.vcn.util.OneWayBoolean;
import android.net.wifi.WifiInfo;
+import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
@@ -171,6 +174,8 @@
*
* @hide
*/
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class VcnGatewayConnection extends StateMachine {
private static final String TAG = VcnGatewayConnection.class.getSimpleName();
@@ -2942,6 +2947,10 @@
*
* <p>Synchronize this action to minimize locking around WakeLock use.
*/
+ // WakelockTimeout suppressed because the time the wake lock is needed for is unknown. The
+ // wakelock is only acquired when a Message is sent to this state machine and will be
+ // released when the message is processed or the state machin quits
+ @SuppressLint("WakelockTimeout")
public synchronized void acquire() {
mImpl.acquire();
}
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java b/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java
index 4552f50..99c848f 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/VcnNetworkProvider.java
@@ -25,6 +25,7 @@
import static com.android.server.VcnManagementService.VDBG;
import android.annotation.NonNull;
+import android.annotation.TargetApi;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
@@ -32,6 +33,7 @@
import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.vcn.VcnGatewayConnectionConfig;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.ArraySet;
@@ -54,6 +56,8 @@
*
* @hide
*/
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class VcnNetworkProvider extends NetworkProvider {
private static final String TAG = VcnNetworkProvider.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
index 72de613..6467af4 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/IpSecPacketLossDetector.java
@@ -23,6 +23,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +32,7 @@
import android.net.IpSecTransformState;
import android.net.Network;
import android.net.vcn.VcnManager;
+import android.os.Build;
import android.os.Handler;
import android.os.OutcomeReceiver;
import android.os.PowerManager;
@@ -59,6 +61,8 @@
*
* <p>This class is flag gated by "network_metric_monitor" and "ipsec_tramsform_state"
*/
+// TODO(b/374174952) Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class IpSecPacketLossDetector extends NetworkMetricMonitor {
private static final String TAG = IpSecPacketLossDetector.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
index 86cee55..1485344 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkMetricMonitor.java
@@ -22,9 +22,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.net.IpSecTransform;
import android.net.IpSecTransformState;
import android.net.Network;
+import android.os.Build;
import android.os.OutcomeReceiver;
import android.util.CloseGuard;
import android.util.Slog;
@@ -42,6 +44,8 @@
*
* <p>This class is flag gated by "network_metric_monitor"
*/
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public abstract class NetworkMetricMonitor implements AutoCloseable {
private static final String TAG = NetworkMetricMonitor.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
index 79c4116..705141f 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -29,12 +29,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.net.NetworkCapabilities;
import android.net.TelephonyNetworkSpecifier;
import android.net.vcn.VcnCellUnderlyingNetworkTemplate;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkTemplate;
import android.net.vcn.VcnWifiUnderlyingNetworkTemplate;
+import android.os.Build;
import android.os.ParcelUuid;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -50,6 +52,8 @@
import java.util.Set;
/** @hide */
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
class NetworkPriorityClassifier {
@NonNull private static final String TAG = NetworkPriorityClassifier.class.getSimpleName();
/**
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
index 29a0762..bc552e7 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
@@ -28,6 +28,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.IpSecTransform;
@@ -40,6 +41,7 @@
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnUnderlyingNetworkTemplate;
import android.net.vcn.util.LogUtils;
+import android.os.Build;
import android.os.Handler;
import android.os.ParcelUuid;
import android.telephony.TelephonyCallback;
@@ -73,6 +75,8 @@
*
* @hide
*/
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class UnderlyingNetworkController {
@NonNull private static final String TAG = UnderlyingNetworkController.class.getSimpleName();
diff --git a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
index 30f4ed1..776931b 100644
--- a/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
+++ b/packages/Vcn/service-b/src/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
@@ -22,12 +22,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TargetApi;
import android.net.IpSecTransform;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkTemplate;
+import android.os.Build;
import android.os.Handler;
import android.os.ParcelUuid;
import android.util.IndentingPrintWriter;
@@ -50,6 +52,8 @@
*
* @hide
*/
+// TODO(b/374174952): Replace VANILLA_ICE_CREAM with BAKLAVA after Android B finalization
+@TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
public class UnderlyingNetworkEvaluator {
private static final String TAG = UnderlyingNetworkEvaluator.class.getSimpleName();
diff --git a/services/Android.bp b/services/Android.bp
index d99ed3d..ebd10cc 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -242,9 +242,11 @@
"services.wifi",
"service-blobstore",
"service-jobscheduler",
- "service-connectivity-b-pre-jarjar", // Move it to mainline module
"android.hidl.base-V1.0-java",
- ],
+ ] + select(release_flag("RELEASE_MOVE_VCN_TO_MAINLINE"), {
+ true: [],
+ default: ["service-connectivity-b-platform"],
+ }),
libs: [
"android.hidl.manager-V1.0-java",
diff --git a/services/art-wear-profile b/services/art-wear-profile
index 47bdb13..42c4a01 100644
--- a/services/art-wear-profile
+++ b/services/art-wear-profile
@@ -7419,7 +7419,7 @@
PLcom/android/server/app/GameManagerService;->updateConfigsForUser(IZ[Ljava/lang/String;)V
PLcom/android/server/app/GameManagerService;->writeGameModeInterventionsToFile(I)V
PLcom/android/server/app/GameManagerSettings;-><init>(Ljava/io/File;)V
-HPLcom/android/server/app/GameManagerSettings;->getConfigOverride(Ljava/lang/String;)Lcom/android/server/app/GameManagerService$GamePackageConfiguration;
+HPLcom/android/server/app/GameManagerSettings;->getConfigOverrideLocked(Ljava/lang/String;)Lcom/android/server/app/GameManagerService$GamePackageConfiguration;
HPLcom/android/server/app/GameManagerSettings;->getGameModeLocked(Ljava/lang/String;)I
PLcom/android/server/app/GameManagerSettings;->readPersistentDataLocked()Z
PLcom/android/server/appbinding/AppBindingConstants;-><init>(Ljava/lang/String;)V
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 349f3ee..9a55603 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -147,6 +147,9 @@
// Java/AIDL sources to be moved out to CrashRecovery module
":services-crashrecovery-sources",
+
+ // Indicate whether VCN is in platform or mainline
+ ":vcn-location-sources",
],
libs: [
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 5f637a3..58ef814 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -1422,10 +1422,10 @@
}
final GameManagerSettings settings = mSettings.get(userId);
// look for the existing GamePackageConfiguration override
- configOverride = settings.getConfigOverride(packageName);
+ configOverride = settings.getConfigOverrideLocked(packageName);
if (configOverride == null) {
configOverride = new GamePackageConfiguration(packageName);
- settings.setConfigOverride(packageName, configOverride);
+ settings.setConfigOverrideLocked(packageName, configOverride);
}
}
GamePackageConfiguration.GameModeConfiguration internalConfig =
@@ -1758,10 +1758,10 @@
}
final GameManagerSettings settings = mSettings.get(userId);
// look for the existing GamePackageConfiguration override
- configOverride = settings.getConfigOverride(packageName);
+ configOverride = settings.getConfigOverrideLocked(packageName);
if (configOverride == null) {
configOverride = new GamePackageConfiguration(packageName);
- settings.setConfigOverride(packageName, configOverride);
+ settings.setConfigOverrideLocked(packageName, configOverride);
}
}
// modify GameModeConfiguration intervention settings
@@ -1800,7 +1800,7 @@
}
final GameManagerSettings settings = mSettings.get(userId);
if (gameModeToReset != -1) {
- final GamePackageConfiguration configOverride = settings.getConfigOverride(
+ final GamePackageConfiguration configOverride = settings.getConfigOverrideLocked(
packageName);
if (configOverride == null) {
return;
@@ -1811,10 +1811,10 @@
}
configOverride.removeModeConfig(gameModeToReset);
if (!configOverride.hasActiveGameModeConfig()) {
- settings.removeConfigOverride(packageName);
+ settings.removeConfigOverrideLocked(packageName);
}
} else {
- settings.removeConfigOverride(packageName);
+ settings.removeConfigOverrideLocked(packageName);
}
}
@@ -2029,7 +2029,7 @@
synchronized (mLock) {
if (mSettings.containsKey(userId)) {
- overrideConfig = mSettings.get(userId).getConfigOverride(packageName);
+ overrideConfig = mSettings.get(userId).getConfigOverrideLocked(packageName);
}
}
if (overrideConfig == null || config == null) {
@@ -2074,7 +2074,7 @@
}
synchronized (mLock) {
if (mSettings.containsKey(userId)) {
- mSettings.get(userId).removeGame(packageName);
+ mSettings.get(userId).removeGameLocked(packageName);
}
sendUserMessage(userId, WRITE_SETTINGS,
Intent.ACTION_PACKAGE_REMOVED, WRITE_DELAY_MILLIS);
diff --git a/services/core/java/com/android/server/app/GameManagerSettings.java b/services/core/java/com/android/server/app/GameManagerSettings.java
index b084cf3..c57a1f7 100644
--- a/services/core/java/com/android/server/app/GameManagerSettings.java
+++ b/services/core/java/com/android/server/app/GameManagerSettings.java
@@ -116,7 +116,7 @@
* Removes all game settings of a given package.
* This operation must be synced with an external lock.
*/
- void removeGame(String packageName) {
+ void removeGameLocked(String packageName) {
mGameModes.remove(packageName);
mConfigOverrides.remove(packageName);
}
@@ -125,7 +125,7 @@
* Returns the game config override of a given package or null if absent.
* This operation must be synced with an external lock.
*/
- GamePackageConfiguration getConfigOverride(String packageName) {
+ GamePackageConfiguration getConfigOverrideLocked(String packageName) {
return mConfigOverrides.get(packageName);
}
@@ -133,7 +133,7 @@
* Sets the game config override of a given package.
* This operation must be synced with an external lock.
*/
- void setConfigOverride(String packageName, GamePackageConfiguration configOverride) {
+ void setConfigOverrideLocked(String packageName, GamePackageConfiguration configOverride) {
mConfigOverrides.put(packageName, configOverride);
}
@@ -141,7 +141,7 @@
* Removes the game mode config override of a given package.
* This operation must be synced with an external lock.
*/
- void removeConfigOverride(String packageName) {
+ void removeConfigOverrideLocked(String packageName) {
mConfigOverrides.remove(packageName);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b22bc2b..0e0b518 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3019,6 +3019,16 @@
mDexOptHelper.performPackageDexOptUpgradeIfNeeded();
}
+ public void updateMetricsIfNeeded() {
+ final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ if (displayManager != null) {
+ final Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ if (display != null) {
+ display.getMetrics(mMetrics);
+ }
+ }
+ }
+
private void notifyPackageUseInternal(String packageName, int reason) {
long time = System.currentTimeMillis();
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index ecffd38..3f9144f 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -136,7 +136,8 @@
final LocationManagerInternal locationManagerInternal = LocalServices.getService(
LocationManagerInternal.class);
- locationManagerInternal.setLocationPackageTagsListener(
+ if (locationManagerInternal != null) {
+ locationManagerInternal.setLocationPackageTagsListener(
(uid, packageTagsList) -> {
synchronized (mLock) {
if (packageTagsList.isEmpty()) {
@@ -158,6 +159,7 @@
mLocationTags);
}
});
+ }
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java
index d70a880..e86cb7d 100644
--- a/services/core/java/com/android/server/wm/ContentRecorder.java
+++ b/services/core/java/com/android/server/wm/ContentRecorder.java
@@ -453,15 +453,17 @@
case RECORD_CONTENT_TASK:
// Given the WindowToken of the region to record, retrieve the associated
// SurfaceControl.
- if (tokenToRecord == null) {
+ final WindowContainer wc = tokenToRecord != null
+ ? WindowContainer.fromBinder(tokenToRecord) : null;
+ if (wc == null) {
handleStartRecordingFailed();
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
- "Content Recording: Unable to start recording due to null token for "
- + "display %d",
+ "Content Recording: Unable to start recording due to null token or " +
+ "null window container for " + "display %d",
mDisplayContent.getDisplayId());
return null;
}
- Task taskToRecord = WindowContainer.fromBinder(tokenToRecord).asTask();
+ final Task taskToRecord = wc.asTask();
if (taskToRecord == null) {
handleStartRecordingFailed();
ProtoLog.v(WM_DEBUG_CONTENT_RECORDING,
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 673d82d..fcb6036 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3254,7 +3254,8 @@
// just kill it. And if it is a window of foreground activity, the activity can be
// restarted automatically if needed.
Slog.w(TAG, "Exception thrown during dispatchAppVisibility " + this, e);
- if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid) {
+ if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid
+ && android.os.Process.getThreadGroupLeader(mSession.mPid) == mSession.mPid) {
android.os.Process.killProcess(mSession.mPid);
}
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 545f9c9..9cee81f 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -11,7 +11,6 @@
name: "libservices.core",
defaults: ["libservices.core-libs"],
- cpp_std: "c++2a",
cflags: [
"-Wall",
"-Werror",
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 95e7b19..d9af3df 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -564,8 +564,8 @@
jobject clazz) {
std::string path;
- if (!getAttributePathForTask("FreezerState", getpid(), &path)) {
- path = "";
+ if (!CgroupGetAttributePathForTask("FreezerState", getpid(), &path)) {
+ path.clear();
}
return env->NewStringUTF(path.c_str());
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0718f04..51166b1 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -277,6 +277,7 @@
import com.android.server.usage.UsageStatsService;
import com.android.server.usb.UsbService;
import com.android.server.utils.TimingsTraceAndSlog;
+import com.android.server.vcn.VcnLocation;
import com.android.server.vibrator.VibratorManagerService;
import com.android.server.voiceinteraction.VoiceInteractionManagerService;
import com.android.server.vr.VrManagerService;
@@ -1847,6 +1848,10 @@
}
t.traceEnd();
+ t.traceBegin("UpdateMetricsIfNeeded");
+ mPackageManagerService.updateMetricsIfNeeded();
+ t.traceEnd();
+
t.traceBegin("PerformFstrimIfNeeded");
try {
mPackageManagerService.performFstrimIfNeeded();
@@ -2146,10 +2151,13 @@
t.traceBegin("StartVcnManagementService");
try {
- // TODO: b/375213246 When VCN is in mainline module, load it from the apex path.
- // Whether VCN will be in apex or in the platform will be gated by a build system
- // flag.
- mSystemServiceManager.startService(CONNECTIVITY_SERVICE_INITIALIZER_B_CLASS);
+ if (VcnLocation.IS_VCN_IN_MAINLINE) {
+ mSystemServiceManager.startServiceFromJar(
+ CONNECTIVITY_SERVICE_INITIALIZER_B_CLASS,
+ CONNECTIVITY_SERVICE_APEX_PATH);
+ } else {
+ mSystemServiceManager.startService(CONNECTIVITY_SERVICE_INITIALIZER_B_CLASS);
+ }
} catch (Throwable e) {
reportWtf("starting VCN Management Service", e);
}
diff --git a/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java b/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java
index fde3422..17f5ebb 100644
--- a/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java
@@ -130,9 +130,9 @@
assertEquals(GameManager.GAME_MODE_STANDARD, settings.getGameModeLocked(PACKAGE_NAME_4));
// test game mode configs
- assertNull(settings.getConfigOverride(PACKAGE_NAME_1));
- assertNull(settings.getConfigOverride(PACKAGE_NAME_3));
- GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_2);
+ assertNull(settings.getConfigOverrideLocked(PACKAGE_NAME_1));
+ assertNull(settings.getConfigOverrideLocked(PACKAGE_NAME_3));
+ GamePackageConfiguration config = settings.getConfigOverrideLocked(PACKAGE_NAME_2);
assertNotNull(config);
assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_STANDARD));
@@ -152,7 +152,7 @@
assertEquals(batteryConfig.getFpsStr(), GameModeConfiguration.DEFAULT_FPS);
assertFalse(batteryConfig.getUseAngle());
- config = settings.getConfigOverride(PACKAGE_NAME_4);
+ config = settings.getConfigOverrideLocked(PACKAGE_NAME_4);
assertNotNull(config);
GameModeConfiguration customConfig = config.getGameModeConfiguration(
GameManager.GAME_MODE_CUSTOM);
@@ -177,7 +177,7 @@
GameManagerSettings settings = new GameManagerSettings(context.getFilesDir());
assertTrue(settings.readPersistentDataLocked());
- final GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_1);
+ final GamePackageConfiguration config = settings.getConfigOverrideLocked(PACKAGE_NAME_1);
assertNotNull(config);
final GameModeConfiguration batteryConfig = config.getGameModeConfiguration(
GameManager.GAME_MODE_BATTERY);
@@ -218,7 +218,7 @@
assertEquals(2, settings.getGameModeLocked(PACKAGE_NAME_2));
assertEquals(3, settings.getGameModeLocked(PACKAGE_NAME_3));
- final GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_2);
+ final GamePackageConfiguration config = settings.getConfigOverrideLocked(PACKAGE_NAME_2);
assertNotNull(config);
final GameModeConfiguration batteryConfig = config.getGameModeConfiguration(
GameManager.GAME_MODE_BATTERY);
@@ -248,7 +248,7 @@
GameModeConfiguration batteryConfig = config.getOrAddDefaultGameModeConfiguration(
GameManager.GAME_MODE_BATTERY);
batteryConfig.setScaling(0.77f);
- settings.setConfigOverride(PACKAGE_NAME_2, config);
+ settings.setConfigOverrideLocked(PACKAGE_NAME_2, config);
// set config for app4
config = new GamePackageConfiguration(PACKAGE_NAME_4);
@@ -256,15 +256,15 @@
GameManager.GAME_MODE_CUSTOM);
customConfig.setScaling(0.4f);
customConfig.setFpsStr("30");
- settings.setConfigOverride(PACKAGE_NAME_4, config);
+ settings.setConfigOverrideLocked(PACKAGE_NAME_4, config);
settings.writePersistentDataLocked();
// clear the settings in memory
- settings.removeGame(PACKAGE_NAME_1);
- settings.removeGame(PACKAGE_NAME_2);
- settings.removeGame(PACKAGE_NAME_3);
- settings.removeGame(PACKAGE_NAME_4);
+ settings.removeGameLocked(PACKAGE_NAME_1);
+ settings.removeGameLocked(PACKAGE_NAME_2);
+ settings.removeGameLocked(PACKAGE_NAME_3);
+ settings.removeGameLocked(PACKAGE_NAME_4);
// read back in and verify
assertTrue(settings.readPersistentDataLocked());
@@ -273,9 +273,9 @@
assertEquals(1, settings.getGameModeLocked(PACKAGE_NAME_3));
assertEquals(1, settings.getGameModeLocked(PACKAGE_NAME_4));
- config = settings.getConfigOverride(PACKAGE_NAME_1);
+ config = settings.getConfigOverrideLocked(PACKAGE_NAME_1);
assertNull(config);
- config = settings.getConfigOverride(PACKAGE_NAME_2);
+ config = settings.getConfigOverrideLocked(PACKAGE_NAME_2);
assertNotNull(config);
batteryConfig = config.getGameModeConfiguration(GameManager.GAME_MODE_BATTERY);
assertNotNull(batteryConfig);
@@ -292,7 +292,7 @@
assertEquals(performanceConfig.getFpsStr(), "60");
assertTrue(performanceConfig.getUseAngle());
- config = settings.getConfigOverride(PACKAGE_NAME_4);
+ config = settings.getConfigOverrideLocked(PACKAGE_NAME_4);
assertNotNull(config);
customConfig = config.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM);
assertNotNull(customConfig);
diff --git a/services/tests/servicestests/src/com/android/server/utils/LazyJniRegistrarTest.java b/services/tests/servicestests/src/com/android/server/utils/LazyJniRegistrarTest.java
new file mode 100644
index 0000000..a2df73b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/utils/LazyJniRegistrarTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+public class LazyJniRegistrarTest {
+
+ @Test
+ public void testNativeMethodsResolve() throws Exception {
+ // Basic test with a few explicit invocations to make sure methods resolve and don't throw.
+ LazyJniRegistrar.registerConsumerIrService();
+ LazyJniRegistrar.registerGameManagerService();
+ LazyJniRegistrar.registerVrManagerService();
+ }
+
+ @Test
+ public void testAllNativeRegisterMethodsResolve() throws Exception {
+ // Catch-all test to make sure public static register* methods resolve and don't throw.
+ for (Method method : LazyJniRegistrar.class.getDeclaredMethods()) {
+ if (Modifier.isPublic(method.getModifiers())
+ && Modifier.isStatic(method.getModifiers())
+ && method.getName().startsWith("register")) {
+ method.invoke(null);
+ }
+ }
+ }
+
+ // TODO(b/302724778): Remove manual JNI load
+ static {
+ System.loadLibrary("servicestestjni");
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/utils/OWNERS b/services/tests/servicestests/src/com/android/server/utils/OWNERS
index f5b19a1..69b9fa2 100644
--- a/services/tests/servicestests/src/com/android/server/utils/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/utils/OWNERS
@@ -1,5 +1,6 @@
per-file EventLoggerTest.java = file:/platform/frameworks/av:/media/janitors/media_solutions_OWNERS
per-file EventLoggerTest.java = jmtrivi@google.com
+per-file LazyJniRegistrarTest.java = file:/PERFORMANCE_OWNERS
# Bug component : 158088 = per-file AnrTimer*.java
per-file AnrTimer*.java = file:/PERFORMANCE_OWNERS
diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt
index 4a6d4b1..c51c6d6 100644
--- a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt
+++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt
@@ -18,9 +18,11 @@
import android.annotation.SdkConstant
import com.squareup.javapoet.ClassName
+import com.squareup.javapoet.CodeBlock
import com.squareup.javapoet.FieldSpec
import com.squareup.javapoet.JavaFile
import com.squareup.javapoet.MethodSpec
+import com.squareup.javapoet.ParameterizedTypeName
import com.squareup.javapoet.TypeSpec
import java.io.IOException
import javax.annotation.processing.AbstractProcessor
@@ -101,8 +103,8 @@
TypeSpec.classBuilder("SystemFeaturesMetadata")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addJavadoc("@hide")
- .addField(buildFeatureCount(featureVarNames))
- .addMethod(buildFeatureIndexLookup(featureVarNames))
+ .addFeatureCount(featureVarNames)
+ .addFeatureIndexLookup(featureVarNames)
.build()
try {
@@ -120,19 +122,55 @@
return true
}
- private fun buildFeatureCount(featureVarNames: Collection<String>): FieldSpec {
- return FieldSpec.builder(Int::class.java, "SDK_FEATURE_COUNT")
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
- .addJavadoc(
- "# of {@link android.annotation.SdkConstant}` features defined in PackageManager."
- )
- .addJavadoc("\n\n@hide")
- .initializer("\$L", featureVarNames.size)
- .build()
+ private fun TypeSpec.Builder.addFeatureCount(
+ featureVarNames: Collection<String>
+ ): TypeSpec.Builder {
+ return addField(
+ FieldSpec.builder(Int::class.java, "SDK_FEATURE_COUNT")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
+ .addJavadoc(
+ "# of {@link android.annotation.SdkConstant}` features in PackageManager."
+ )
+ .addJavadoc("\n\n@hide")
+ .initializer("\$L", featureVarNames.size)
+ .build()
+ )
}
- private fun buildFeatureIndexLookup(featureVarNames: Collection<String>): MethodSpec {
- val methodBuilder =
+ private fun TypeSpec.Builder.addFeatureIndexLookup(
+ featureVarNames: Collection<String>
+ ): TypeSpec.Builder {
+ // NOTE: This was initially implemented in terms of a single, long switch() statement.
+ // However, this resulted in:
+ // 1) relatively large compiled code size for the lookup method (~20KB)
+ // 2) worse runtime lookup performance than a simple ArraySet
+ // The ArraySet approach adds just ~1KB to the code/image and is 2x faster at runtime.
+
+ // Provide the initial capacity of the ArraySet for efficiency.
+ addField(
+ FieldSpec.builder(
+ ParameterizedTypeName.get(ARRAYSET_CLASS, ClassName.get(String::class.java)),
+ "sFeatures",
+ )
+ .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
+ .initializer("new ArraySet<>(\$L)", featureVarNames.size)
+ .build()
+ )
+
+ // Use a temp array + Collections.addAll() to minimizes the generated code size.
+ addStaticBlock(
+ CodeBlock.builder()
+ .add("final \$T[] features = {\n", String::class.java)
+ .indent()
+ .apply { featureVarNames.forEach { add("\$T.\$N,\n", PACKAGEMANAGER_CLASS, it) } }
+ .unindent()
+ .addStatement("}")
+ .addStatement("\$T.addAll(sFeatures, features)", COLLECTIONS_CLASS)
+ .build()
+ )
+
+ // Use ArraySet.indexOf to provide the implicit feature index mapping.
+ return addMethod(
MethodSpec.methodBuilder("maybeGetSdkFeatureIndex")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addJavadoc("@return an index in [0, SDK_FEATURE_COUNT) for features defined ")
@@ -140,21 +178,15 @@
.addJavadoc("\n\n@hide")
.returns(Int::class.java)
.addParameter(String::class.java, "featureName")
- methodBuilder.beginControlFlow("switch (featureName)")
- featureVarNames.forEachIndexed { index, featureVarName ->
- methodBuilder
- .addCode("case \$T.\$N: ", PACKAGEMANAGER_CLASS, featureVarName)
- .addStatement("return \$L", index)
- }
- methodBuilder
- .addCode("default: ")
- .addStatement("return -1")
- .endControlFlow()
- return methodBuilder.build()
+ .addStatement("return sFeatures.indexOf(featureName)")
+ .build()
+ )
}
companion object {
private val SDK_CONSTANT_ANNOTATION_NAME = SdkConstant::class.qualifiedName
private val PACKAGEMANAGER_CLASS = ClassName.get("android.content.pm", "PackageManager")
+ private val ARRAYSET_CLASS = ClassName.get("android.util", "ArraySet")
+ private val COLLECTIONS_CLASS = ClassName.get("java.util", "Collections")
}
}
diff --git a/tools/systemfeatures/tests/src/ArraySet.java b/tools/systemfeatures/tests/src/ArraySet.java
new file mode 100644
index 0000000..0eb8f29
--- /dev/null
+++ b/tools/systemfeatures/tests/src/ArraySet.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import java.util.ArrayList;
+
+/** Stub for testing, we extend ArrayList to get indexOf() for free. */
+public final class ArraySet<K> extends ArrayList<K> {
+ public ArraySet(int capacity) {
+ super(capacity);
+ }
+
+ @Override
+ public boolean add(K k) {
+ if (!contains(k)) {
+ return super.add(k);
+ }
+ return false;
+ }
+}