diff options
84 files changed, 981 insertions, 308 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 21b1b174e55d..f69fd55beb3a 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -303,6 +303,7 @@ java_aconfig_library { aconfig_declarations { name: "android.security.flags-aconfig", package: "android.security", + exportable: true, container: "system", srcs: ["core/java/android/security/*.aconfig"], } @@ -320,6 +321,19 @@ java_aconfig_library { 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", @@ -34,6 +34,8 @@ per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS 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 BROADCASTS_OWNERS = file:/BROADCASTS_OWNERS 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 000000000000..ece4d3e5e268 --- /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 000000000000..205c7b875bbc --- /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 ed669beae1ce..c77528021201 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 @@ public class ZipFilePerfTest { @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 73bff08c626d..af0237491639 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.Activity; 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 @@ public final class BenchmarkState { } 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 @@ public final class BenchmarkState { 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 @@ public final class BenchmarkState { return true; } mState = FINISHED; + endBenchmark(); return false; } mPausedDurationNs = 0; @@ -189,6 +201,7 @@ public final class BenchmarkState { // 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 @@ public final class BenchmarkState { mCustomizedIterations++; if (mCustomizedIterations >= mMaxCustomizedIterations) { mState = FINISHED; + endBenchmark(); return false; } mCustomizedIterationListener.onStart(mCustomizedIterations); diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp index 1ebe0cdfabd7..796c8412b26c 100644 --- a/api/ApiDocs.bp +++ b/api/ApiDocs.bp @@ -129,6 +129,10 @@ droidstubs { 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 @@ droidstubs { "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 e3a2455ee37f..16852ae78a46 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -13034,6 +13034,7 @@ package android.content.pm { 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 @@ package android.content.pm { 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 @@ package android.text { 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 5790a732f134..b2331cb55fb5 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -129,7 +129,6 @@ package android.content.pm { 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 @@ package android.content.pm { 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 59327c8afecc..7862a361997b 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2385,6 +2385,12 @@ package android.os { 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 759d1919e4e1..fbcefa3edf35 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3116,16 +3116,6 @@ public abstract class PackageManager { 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 @@ public abstract class PackageManager { * 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 @@ public abstract class PackageManager { } 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 e4fbd1f28dbb..21bbb0a0a81c 100644 --- a/core/java/android/content/pm/SigningInfo.java +++ b/core/java/android/content/pm/SigningInfo.java @@ -22,7 +22,6 @@ import android.annotation.FlaggedApi; 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 @@ public final class SigningInfo implements Parcelable { /** * 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 @@ public final class SigningInfo implements Parcelable { /** * 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 a81e07e73685..2fd1bfb46f4c 100644 --- a/core/java/android/content/pm/SigningInfoException.java +++ b/core/java/android/content/pm/SigningInfoException.java @@ -19,17 +19,13 @@ package android.content.pm; 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 901326d759a4..2b8780c4fba0 100644 --- a/core/java/android/content/pm/flags.aconfig +++ b/core/java/android/content/pm/flags.aconfig @@ -149,6 +149,13 @@ flag { } 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 f7dc7906d50d..a30cd5cfe23a 100644 --- a/core/java/android/net/flags.aconfig +++ b/core/java/android/net/flags.aconfig @@ -28,3 +28,11 @@ flag { 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 d0828c384664..eaecd34b9d75 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -20,6 +20,7 @@ import android.annotation.FlaggedApi; 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 @@ public class Handler { *@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 @@ public class Handler { *@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 @@ public class Handler { * @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 ddf2b61324ad..012590510714 100644 --- a/core/java/android/os/Looper.java +++ b/core/java/android/os/Looper.java @@ -332,16 +332,55 @@ public final class Looper { 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 8d353384f1e2..f3bb51490f20 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -115,13 +115,20 @@ per-file ProfilingServiceManager.java = file:/PERFORMANCE_OWNERS # 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 851953af1fb9..80a8dbe491be 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -560,10 +560,9 @@ public class Process { * 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 @@ public class Process { } /** - * 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 49b696d95723..7ea521ec5dd4 100644 --- a/core/java/android/os/ServiceManagerNative.java +++ b/core/java/android/os/ServiceManagerNative.java @@ -50,7 +50,8 @@ public final class ServiceManagerNative { 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 6045344126c0..26fc8fae8f45 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 6ea462eb969f..71c9a2a888be 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -675,7 +675,7 @@ public class TextUtils { * @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 78427fe91088..f15dbd65832a 100644 --- a/core/java/com/android/internal/app/NfcResolverActivity.java +++ b/core/java/com/android/internal/app/NfcResolverActivity.java @@ -34,13 +34,13 @@ public class NfcResolverActivity extends ResolverActivity { @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 19c6f51ff9a7..9bd52372e6c4 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1326,7 +1326,7 @@ public class LockPatternUtils { 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 4369cb0d82b4..22d5ab874fb7 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -584,32 +584,6 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz, 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 @@ static const JNINativeMethod methods[] = { {"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 76ead2a3ca31..48c92c87f54e 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 @@ bool punchWithBlockAlignment(borrowed_fd fd, uint64_t start, uint64_t length, ui 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 @@ bool punchWithBlockAlignment(borrowed_fd fd, uint64_t start, uint64_t length, ui 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 @@ bool punchHoles(const char *filePath, const uint64_t offset, 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 @@ bool punchHoles(const char *filePath, const uint64_t offset, 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 @@ bool punchHolesInZip(const char *filePath, uint64_t offset, uint16_t extraFieldL 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 @@ bool punchHolesInZip(const char *filePath, uint64_t offset, uint16_t extraFieldL 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 aeaeeca3e845..8c7b335e6e86 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 087378bef6a1..3da69e854b63 100644 --- a/framework-jarjar-rules.txt +++ b/framework-jarjar-rules.txt @@ -10,3 +10,6 @@ rule com.android.modules.utils.build.** android.internal.modules.utils.build.@1 # 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 4287daa03223..4f22c14c139d 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 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, 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 fc184fe5c872..8419ce761a4a 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -1149,9 +1149,9 @@ status_t JMediaCodec::unsubscribeFromVendorParameters(JNIEnv *env, jobject names 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 @@ static jobject getJavaResources( } 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 void android_media_MediaCodec_unsubscribeFromVendorParameters( 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 getJavaResources( 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 abe0ab757ba6..c33665aef41d 100644 --- a/nfc/Android.bp +++ b/nfc/Android.bp @@ -56,7 +56,7 @@ java_sdk_library { ], 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 @@ java_sdk_library { "//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 35e9713f5715..f46dccd97974 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 0ee81cbb7a73..c8c479a4d2ad 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -211,7 +211,7 @@ package android.nfc.cardemulation { 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 @@ package android.nfc.cardemulation { 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 @@ package android.nfc.cardemulation { 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 bb9fe959dc06..00ceaa9801d8 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 @@ interface INfcCardEmulation 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 index 774d8f875192..af1fa2fb2456 100644 --- a/nfc/java/android/nfc/INfcEventListener.aidl +++ b/nfc/java/android/nfc/INfcEventCallback.aidl @@ -5,7 +5,7 @@ import android.nfc.ComponentNameAndUser; /** * @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 89ce4239cd4d..63397c21b036 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -1789,6 +1789,11 @@ public final class NfcAdapter { * @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 e0bc15fe6e94..fee9c5bfa328 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -39,7 +39,7 @@ import android.nfc.ComponentNameAndUser; 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 @@ public final class CardEmulation { /** 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 @@ public final class CardEmulation { /** * 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 @@ public final class CardEmulation { 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 @@ public final class CardEmulation { } 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 @@ public final class CardEmulation { * @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 db1f6a2bb3b1..fbf2203b40b4 100644 --- a/nfc/java/android/nfc/cardemulation/HostApduService.java +++ b/nfc/java/android/nfc/cardemulation/HostApduService.java @@ -289,7 +289,7 @@ public abstract class HostApduService extends Service { 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 35e9713f5715..000000000000 --- 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 35e9713f5715..000000000000 --- 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 35e9713f5715..000000000000 --- 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 000000000000..c24816d85517 --- /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 000000000000..7e0010247ee7 --- /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 c3ecff418075..dd939bbe041e 100644 --- a/packages/Shell/OWNERS +++ b/packages/Shell/OWNERS @@ -12,3 +12,7 @@ cbrubaker@google.com 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 bcfd8f620f9c..75156bac3dc4 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -236,6 +236,9 @@ public class BugreportProgressService extends Service { /** 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 @@ public class BugreportProgressService extends Service { 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 @@ public class BugreportProgressService extends Service { */ 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 @@ public class BugreportProgressService extends Service { 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 @@ public class BugreportProgressService extends Service { } } 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 050a3704df1f..7bda2ea790b0 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { // 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { 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 @@ public class BugreportReceiverTest { sendBugreportFinished(); killService(); assertServiceNotRunning(); - Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId); + Bundle extras = acceptBugreportAndGetSharedIntent(mBugreportId, 1); assertActionSendMultiple(extras); } @@ -618,45 +633,49 @@ public class BugreportReceiverTest { * 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 ce9f70d8b977..60008a353d81 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 @@ package com.android.shell; 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.assertFalse; 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 @@ final class UiBot { * * @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 42733a20ffae..0c29bb4b2279 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 d51831b5730f..261ffa06e105 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 3943c6f7fe24..8d09fdbfa3de 100644 --- a/packages/Vcn/flags/Android.bp +++ b/packages/Vcn/flags/Android.bp @@ -29,10 +29,24 @@ aconfig_declarations { ], } +// 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 c3121162b7f2..edb22c0e7aa0 100644 --- a/packages/Vcn/framework-b/Android.bp +++ b/packages/Vcn/framework-b/Android.bp @@ -32,9 +32,9 @@ filegroup { } 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 @@ java_defaults { 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 @@ java_defaults { }, } +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 @@ java_sdk_library { "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 @@ java_sdk_library { "//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 000000000000..757043bdbbc0 --- /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 757043bdbbc0..7e27b24f749c 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 1f0fa92d7976..de22ca684871 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.Nullable; 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 @@ import android.os.SystemProperties; @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 @@ public final class ConnectivityFrameworkInitializerBaklava { 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 c1a1ee7875d0..1370b0678cc5 100644 --- a/packages/Vcn/service-b/Android.bp +++ b/packages/Vcn/service-b/Android.bp @@ -32,11 +32,9 @@ filegroup { 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 @@ java_library { "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 @@ java_library { "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 000000000000..36307277b4b9 --- /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 02c8ce4f29e9..81c7edf4adf1 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 @@ import com.android.tools.r8.keepanno.annotations.UsedByReflection; // 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 26db6a988e31..c9a99d729e91 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 static java.util.Objects.requireNonNull; 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 @@ import java.util.concurrent.TimeUnit; * @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 @@ public class VcnManagementService extends IVcnManagementService.Stub { }); } - // 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 b448f7595b3b..b04e25dff276 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 static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED 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 @@ 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) 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 2524d0eedac3..369ef6ae6a3f 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 static com.android.server.VcnManagementService.VDBG; 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.VcnConfig; 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 @@ 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) 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 e50fc3a6e8b9..300b80f942ef 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 static com.android.server.VcnManagementService.VDBG; 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.LogUtils; 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 @@ import java.util.function.Consumer; * * @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 @@ public class VcnGatewayConnection extends StateMachine { * * <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 4552f509b59a..99c848f53c39 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 android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 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.NetworkProvider; 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 @@ import java.util.concurrent.Executor; * * @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 72de61363d26..6467af4355f6 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 static com.android.internal.annotations.VisibleForTesting.Visibility; 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.ConnectivityManager; 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 @@ import java.util.concurrent.TimeUnit; * * <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 86cee554be6f..14853440a129 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 static com.android.server.VcnManagementService.LOCAL_LOG; 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 @@ import java.util.concurrent.Executor; * * <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 79c4116d0cd4..705141f3f1b4 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 static com.android.server.VcnManagementService.LOCAL_LOG; 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.Map; 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 29a0762f5fe8..bc552e7e6afd 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 static com.android.server.vcn.routeselection.NetworkPriorityClassifier.ge 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.VcnCellUnderlyingNetworkTemplate; 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 @@ import java.util.TreeSet; * * @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 30f4ed1b9f0b..776931bad73b 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 static com.android.server.VcnManagementService.LOCAL_LOG; 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 @@ import java.util.concurrent.TimeUnit; * * @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 d99ed3dbdba8..ebd10cc26d16 100644 --- a/services/Android.bp +++ b/services/Android.bp @@ -242,9 +242,11 @@ java_library { "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 47bdb1385137..42c4a01c5c2f 100644 --- a/services/art-wear-profile +++ b/services/art-wear-profile @@ -7419,7 +7419,7 @@ PLcom/android/server/app/GameManagerService;->sendUserMessage(IILjava/lang/Strin 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 349f3ee2b9f0..9a5560345a22 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -147,6 +147,9 @@ java_library_static { // 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 5f637a39674d..58ef814b67df 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 @@ public final class GameManagerService extends IGameManagerService.Stub { } 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 @@ public final class GameManagerService extends IGameManagerService.Stub { } 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 @@ public final class GameManagerService extends IGameManagerService.Stub { } 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 @@ public final class GameManagerService extends IGameManagerService.Stub { } configOverride.removeModeConfig(gameModeToReset); if (!configOverride.hasActiveGameModeConfig()) { - settings.removeConfigOverride(packageName); + settings.removeConfigOverrideLocked(packageName); } } else { - settings.removeConfigOverride(packageName); + settings.removeConfigOverrideLocked(packageName); } } @@ -2029,7 +2029,7 @@ public final class GameManagerService extends IGameManagerService.Stub { 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 @@ public final class GameManagerService extends IGameManagerService.Stub { } 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 b084cf3c3b12..c57a1f73d7d7 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 @@ public class GameManagerSettings { * 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 @@ public class GameManagerSettings { * 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 @@ public class GameManagerSettings { * 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 @@ public class GameManagerSettings { * 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 b22bc2b8c5be..0e0b518bf3b9 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 @@ public class PackageManagerService implements PackageSender, TestUtilityService 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 ecffd382f542..3f9144f0d980 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 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat 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 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat 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 d70a88062ebd..e86cb7d96ccf 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 @@ final class ContentRecorder implements WindowContainerListener { 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 673d82d4d35f..fcb603628240 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 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // 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 545f9c99cd7a..9cee81fdde40 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -11,7 +11,6 @@ cc_library_static { 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 95e7b198c1bb..d9af3df6e0d6 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 @@ static jstring com_android_server_am_CachedAppOptimizer_getFreezerCheckPath(JNIE 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 0718f043ae2a..51166b157797 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.StorageStatsService; 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 @@ public final class SystemServer implements Dumpable { } t.traceEnd(); + t.traceBegin("UpdateMetricsIfNeeded"); + mPackageManagerService.updateMetricsIfNeeded(); + t.traceEnd(); + t.traceBegin("PerformFstrimIfNeeded"); try { mPackageManagerService.performFstrimIfNeeded(); @@ -2146,10 +2151,13 @@ public final class SystemServer implements Dumpable { 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 fde3422b1ff3..17f5ebb3b02a 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 @@ public class GameManagerServiceSettingsTests { 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 @@ public class GameManagerServiceSettingsTests { 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 @@ public class GameManagerServiceSettingsTests { 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 @@ public class GameManagerServiceSettingsTests { 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 @@ public class GameManagerServiceSettingsTests { 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 @@ public class GameManagerServiceSettingsTests { 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 @@ public class GameManagerServiceSettingsTests { 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 @@ public class GameManagerServiceSettingsTests { 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 000000000000..a2df73b7d540 --- /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 f5b19a1c40ae..69b9fa23c040 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 4a6d4b1f49ef..c51c6d661314 100644 --- a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt +++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt @@ -18,9 +18,11 @@ package com.android.systemfeatures 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 @@ class SystemFeaturesMetadataProcessor : AbstractProcessor() { 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 @@ class SystemFeaturesMetadataProcessor : AbstractProcessor() { 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 @@ class SystemFeaturesMetadataProcessor : AbstractProcessor() { .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 000000000000..0eb8f298bd89 --- /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; + } +} |