summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp8
-rw-r--r--ApiDocs.bp45
-rw-r--r--StubLibraries.bp57
-rw-r--r--apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java17
-rw-r--r--apct-tests/perftests/core/src/android/opengl/perftests/MatrixPerfTest.java397
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java7
-rw-r--r--api/Android.bp18
-rw-r--r--api/api.go95
-rw-r--r--cmds/incidentd/src/IncidentService.cpp6
-rw-r--r--core/api/current.txt3
-rw-r--r--core/java/android/accessibilityservice/OWNERS6
-rw-r--r--core/java/android/accounts/Account.java7
-rw-r--r--core/java/android/app/ActivityManager.java12
-rw-r--r--core/java/android/app/ActivityOptions.java5
-rw-r--r--core/java/android/app/OWNERS2
-rw-r--r--core/java/android/companion/OWNERS4
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java2
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java4
-rw-r--r--core/java/android/hardware/camera2/params/MandatoryStreamCombination.java27
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulation.java72
-rw-r--r--core/java/android/nfc/cardemulation/NfcFCardEmulation.java26
-rw-r--r--core/java/android/os/FileUtils.java81
-rw-r--r--core/java/android/os/Parcel.java4
-rw-r--r--core/java/android/os/Process.java19
-rw-r--r--core/java/android/provider/DeviceConfig.java8
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java1
-rw-r--r--core/java/android/service/resumeonreboot/OWNERS3
-rw-r--r--core/java/android/text/OWNERS8
-rw-r--r--core/java/android/view/accessibility/OWNERS4
-rw-r--r--core/java/android/widget/OWNERS4
-rw-r--r--core/java/android/widget/RemoteViews.java11
-rw-r--r--core/java/com/android/internal/accessibility/OWNERS6
-rw-r--r--core/java/com/android/internal/display/BrightnessSynchronizer.java32
-rw-r--r--core/java/com/android/internal/widget/LocalImageResolver.java7
-rw-r--r--core/jni/android_media_AudioSystem.cpp2
-rw-r--r--core/jni/android_os_Parcel.cpp11
-rw-r--r--core/jni/android_util_Binder.cpp6
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/os/FileUtilsTest.java54
-rw-r--r--core/tests/coretests/src/android/os/ProcessTest.java3
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java9
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java42
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java11
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java16
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp3
-rw-r--r--libs/hwui/Layer.h6
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.cpp27
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp4
-rw-r--r--libs/incident/Android.bp2
-rw-r--r--media/Android.bp5
-rw-r--r--media/aidl/android/media/audio/common/Boolean.aidl29
-rw-r--r--media/aidl/android/media/audio/common/Byte.aidl29
-rw-r--r--media/aidl/android/media/audio/common/Double.aidl29
-rw-r--r--media/aidl/android/media/audio/common/Float.aidl29
-rw-r--r--media/aidl/android/media/audio/common/Long.aidl29
-rw-r--r--media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Boolean.aidl39
-rw-r--r--media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Byte.aidl39
-rw-r--r--media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Double.aidl39
-rw-r--r--media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Float.aidl39
-rw-r--r--media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Long.aidl39
-rw-r--r--media/java/android/media/MediaMuxer.java23
-rw-r--r--media/jni/android_media_MediaMuxer.cpp6
-rw-r--r--media/native/midi/Android.bp4
-rw-r--r--media/native/midi/include/amidi/AMidi.h4
-rw-r--r--native/android/Android.bp3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java20
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/Android.bp2
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java134
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java15
-rw-r--r--packages/SystemUI/tests/Android.bp50
-rw-r--r--packages/SystemUI/tests/Android.mk93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java205
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java138
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java2
-rw-r--r--services/accessibility/OWNERS2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java9
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java14
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java54
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java16
-rw-r--r--services/companion/java/com/android/server/companion/virtual/OWNERS1
-rw-r--r--services/core/java/com/android/server/NetworkTimeUpdateService.java40
-rw-r--r--services/core/java/com/android/server/OWNERS3
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java2
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java12
-rw-r--r--services/core/java/com/android/server/am/AppRestrictionController.java33
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java2
-rw-r--r--services/core/java/com/android/server/am/ProcessProfileRecord.java13
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java7
-rw-r--r--services/core/java/com/android/server/am/ProcessStateRecord.java13
-rw-r--r--services/core/java/com/android/server/am/SettingsToPropertiesMapper.java1
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java150
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java17
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java26
-rw-r--r--services/core/java/com/android/server/audio/PlaybackActivityMonitor.java159
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java73
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java4
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java16
-rw-r--r--services/core/java/com/android/server/locksettings/OWNERS3
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java19
-rw-r--r--services/core/java/com/android/server/notification/SnoozeHelper.java11
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java20
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java8
-rw-r--r--services/core/java/com/android/server/resources/OWNERS4
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java1
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java1
-rw-r--r--services/core/java/com/android/server/wm/StartingSurfaceController.java5
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java2
-rw-r--r--services/core/jni/OWNERS1
-rw-r--r--services/core/jni/com_android_server_companion_virtual_InputController.cpp9
-rw-r--r--services/incremental/IncrementalService.cpp4
-rw-r--r--services/incremental/test/IncrementalServiceTest.cpp8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt2
-rw-r--r--services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java21
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java85
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java17
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java35
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java11
-rw-r--r--tests/Codegen/Android.bp8
-rw-r--r--tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java2
-rw-r--r--tests/HandwritingIme/OWNERS3
-rw-r--r--tests/RollbackTest/Android.bp1
-rw-r--r--tests/TrustTests/Android.bp2
-rw-r--r--tools/aapt2/ResourceUtils.cpp9
-rw-r--r--tools/aapt2/cmd/Link.h2
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp17
-rw-r--r--tools/aapt2/link/ManifestFixer.h3
-rw-r--r--tools/aapt2/link/ManifestFixer_test.cpp48
-rw-r--r--tools/lint/OWNERS3
-rw-r--r--tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt12
-rw-r--r--tools/preload/loadclass/LoadClass.java8
-rw-r--r--tools/processors/staledataclass/Android.bp18
-rw-r--r--tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt1
-rw-r--r--tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt2
-rw-r--r--tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java2
-rw-r--r--tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java4
158 files changed, 2914 insertions, 725 deletions
diff --git a/Android.bp b/Android.bp
index 0f9977cb65b3..c22dafb670a3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -289,6 +289,14 @@ java_defaults {
"staledataclass-annotation-processor",
"error_prone_android_framework",
],
+ // Exports needed for staledataclass-annotation-processor, see b/139342589.
+ javacflags: [
+ "-J--add-modules=jdk.compiler",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+ ],
required: [
// TODO(b/120066492): remove default_television.xml when the build system
// propagates "required" properly.
diff --git a/ApiDocs.bp b/ApiDocs.bp
index c87ecde4e5c8..bf3a6a356e31 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -122,17 +122,30 @@ droidstubs {
}
droidstubs {
- name: "framework-doc-system-stubs",
- defaults: ["framework-doc-stubs-sources-default"],
+ name: "android-non-updatable-doc-stubs-module-lib",
+ defaults: [
+ "android-non-updatable-doc-stubs-defaults",
+ "module-classpath-stubs-defaults",
+ ],
args: metalava_framework_docs_args +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\) ",
+ generate_stubs: false, // We're only using this module for the annotations.zip output, disable doc-stubs.
+ write_sdk_values: false,
+}
+
+droidstubs {
+ name: "android-non-updatable-doc-stubs-system-server",
+ defaults: [
+ "android-non-updatable-doc-stubs-defaults",
+ "module-classpath-stubs-defaults",
],
- api_levels_sdk_type: "system",
- extensions_info_file: ":sdk-extensions-info",
+ args: metalava_framework_docs_args +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\) " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\) ",
+ generate_stubs: false, // We're only using this module for the annotations.zip output, disable doc-stubs.
+ write_sdk_values: false,
}
droidstubs {
@@ -150,6 +163,20 @@ droidstubs {
extensions_info_file: ":sdk-extensions-info",
}
+droidstubs {
+ name: "framework-doc-system-stubs",
+ defaults: ["framework-doc-stubs-sources-default"],
+ args: metalava_framework_docs_args +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ api_levels_sdk_type: "system",
+ extensions_info_file: ":sdk-extensions-info",
+}
+
/////////////////////////////////////////////////////////////////////
// API docs are created from the generated stub source files
// using droiddoc
diff --git a/StubLibraries.bp b/StubLibraries.bp
index bc2e6dd79fea..0e084968410f 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -411,6 +411,36 @@ java_library {
],
}
+java_library {
+ name: "android_module_stubs_current_with_test_libs",
+ static_libs: [
+ "android_module_lib_stubs_current",
+ "android.test.base.stubs",
+ "android.test.mock.stubs",
+ "android.test.runner.stubs",
+ ],
+ defaults: ["android.jar_defaults"],
+ visibility: [
+ "//visibility:override",
+ "//visibility:private",
+ ],
+}
+
+java_library {
+ name: "android_system_server_stubs_current_with_test_libs",
+ static_libs: [
+ "android_system_server_stubs_current",
+ "android.test.base.stubs.system",
+ "android.test.mock.stubs.system",
+ "android.test.runner.stubs.system",
+ ],
+ defaults: ["android.jar_defaults"],
+ visibility: [
+ "//visibility:override",
+ "//visibility:private",
+ ],
+}
+
droidstubs {
name: "api_versions_public",
srcs: [":android_stubs_current_with_test_libs{.jar}"],
@@ -420,6 +450,7 @@ droidstubs {
"sdk-dir",
"api-versions-jars-dir",
],
+ api_levels_sdk_type: "public",
extensions_info_file: ":sdk-extensions-info",
}
@@ -436,6 +467,32 @@ droidstubs {
extensions_info_file: ":sdk-extensions-info",
}
+droidstubs {
+ name: "api_versions_module_lib",
+ srcs: [":android_module_stubs_current_with_test_libs{.jar}"],
+ generate_stubs: false,
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ api_levels_sdk_type: "module-lib",
+ extensions_info_file: ":sdk-extensions-info",
+}
+
+droidstubs {
+ name: "api_versions_system_server",
+ srcs: [":android_system_server_stubs_current_with_test_libs{.jar}"],
+ generate_stubs: false,
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ api_levels_sdk_type: "system-server",
+ extensions_info_file: ":sdk-extensions-info",
+}
+
/////////////////////////////////////////////////////////////////////
// hwbinder.stubs provides APIs required for building HIDL Java
// libraries.
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java
index 34fb88bf8627..10fa8b93acaf 100644
--- a/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java
@@ -20,28 +20,19 @@ import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.test.suitebuilder.annotation.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-import java.util.Arrays;
-import java.util.Collection;
/** Tests the performance of various StringBuilder methods. */
-@RunWith(Parameterized.class)
+@RunWith(AndroidJUnit4.class)
@LargeTest
public class StringBuilderPerfTest {
@Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
- @Parameters(name = "mLength={0}")
- public static Collection<Object[]> data() {
- return Arrays.asList(new Object[][] {{1}, {10}, {100}});
- }
-
- @Parameterized.Parameter(0)
- public int mLength;
+ public int mLength = 100;
@Test
public void timeAppendBoolean() {
diff --git a/apct-tests/perftests/core/src/android/opengl/perftests/MatrixPerfTest.java b/apct-tests/perftests/core/src/android/opengl/perftests/MatrixPerfTest.java
new file mode 100644
index 000000000000..b29614817ee2
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/opengl/perftests/MatrixPerfTest.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.opengl.perftests;
+
+import android.opengl.Matrix;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.Random;
+
+@LargeTest
+public class MatrixPerfTest {
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ @Rule
+ public float[] array = new float[48];
+
+ @Rule
+ public float[] bigArray = new float[16 * 1024 * 1024];
+
+
+ @Test
+ public void testMultiplyMM() {
+ Random rng = new Random();
+ for (int i = 0; i < 32; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMM(array, 32, array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMMLeftOverlapResult() {
+ Random rng = new Random();
+ for (int i = 0; i < 32; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMM(array, 16, array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMMRightOverlapResult() {
+ Random rng = new Random();
+ for (int i = 0; i < 32; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMM(array, 0, array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMMAllOverlap() {
+ Random rng = new Random();
+ for (int i = 0; i < 16; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMM(array, 0, array, 0, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMMOutputBigArray() {
+ Random rng = new Random();
+ for (int i = 0; i < 32; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMM(bigArray, 1024, array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMMAllBigArray() {
+ Random rng = new Random();
+ for (int i = 0; i < 32; i++) {
+ bigArray[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMM(bigArray, 1024, bigArray, 16, bigArray, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMV() {
+ Random rng = new Random();
+ for (int i = 0; i < 20; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMV(array, 20, array, 4, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMVLeftOverlapResult() {
+ Random rng = new Random();
+ for (int i = 0; i < 20; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMV(array, 4, array, 4, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMVRightOverlapResult() {
+ Random rng = new Random();
+ for (int i = 0; i < 32; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMV(array, 0, array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMVAllOverlap() {
+ Random rng = new Random();
+ for (int i = 0; i < 16; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMV(array, 0, array, 0, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMVOutputBigArray() {
+ Random rng = new Random();
+ for (int i = 0; i < 20; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMV(bigArray, 1024, array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testMultiplyMVAllBigArray() {
+ Random rng = new Random();
+ for (int i = 0; i < 20; i++) {
+ bigArray[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.multiplyMV(bigArray, 1024, bigArray, 16, bigArray, 0);
+ }
+ }
+
+ @Test
+ public void testTransposeM() {
+ Random rng = new Random();
+ for (int i = 0; i < 16; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.transposeM(array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testInvertM() {
+ // non-singular matrix
+ array[ 0] = 0.814f;
+ array[ 1] = 4.976f;
+ array[ 2] = -3.858f;
+ array[ 3] = 7.206f;
+ array[ 4] = 5.112f;
+ array[ 5] = -2.420f;
+ array[ 6] = 8.791f;
+ array[ 7] = 6.426f;
+ array[ 8] = 2.945f;
+ array[ 9] = 1.801f;
+ array[10] = -2.594f;
+ array[11] = 2.663f;
+ array[12] = -5.003f;
+ array[13] = -4.188f;
+ array[14] = 3.340f;
+ array[15] = -1.235f;
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.invertM(array, 16, array, 0);
+ }
+ }
+
+ @Test
+ public void testOrthoM() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.orthoM(array, 0, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
+ }
+ }
+
+ @Test
+ public void testFrustumM() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.frustumM(array, 0, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
+ }
+ }
+
+ @Test
+ public void testPerspectiveM() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.perspectiveM(array, 0, 45.0f, 1.0f, 1.0f, 100.0f);
+ }
+ }
+
+ @Test
+ public void testLength() {
+ Random rng = new Random();
+ for (int i = 0; i < 3; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.length(array[0], array[1], array[2]);
+ }
+ }
+
+ @Test
+ public void testSetIdentityM() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.setIdentityM(array, 0);
+ }
+ }
+
+ @Test
+ public void testScaleM() {
+ Random rng = new Random();
+ for (int i = 0; i < 19; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.scaleM(array, 19, array, 0, array[16], array[17], array[18]);
+ }
+ }
+
+ @Test
+ public void testScaleMInPlace() {
+ Random rng = new Random();
+ for (int i = 0; i < 19; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.scaleM(array, 0, array[16], array[17], array[18]);
+ }
+ }
+
+ @Test
+ public void testTranslateM() {
+ Random rng = new Random();
+ for (int i = 0; i < 19; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.translateM(array, 19, array, 0, array[16], array[17], array[18]);
+ }
+ }
+
+ @Test
+ public void testTranslateMInPlace() {
+ Random rng = new Random();
+ for (int i = 0; i < 19; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.translateM(array, 0, array[16], array[17], array[18]);
+ }
+ }
+
+ @Test
+ public void testRotateM() {
+ Random rng = new Random();
+ for (int i = 0; i < 20; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.rotateM(array, 20, array, 0, array[16], array[17], array[18], array[19]);
+ }
+ }
+
+ @Test
+ public void testRotateMInPlace() {
+ Random rng = new Random();
+ for (int i = 0; i < 20; i++) {
+ array[i] = rng.nextFloat();
+ }
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.rotateM(array, 0, array[16], array[17], array[18], array[19]);
+ }
+ }
+
+ @Test
+ public void testSetRotateM() {
+ Random rng = new Random();
+ array[0] = rng.nextFloat() * 90.0f;
+ array[1] = rng.nextFloat() + 0.5f;
+ array[2] = rng.nextFloat() + 0.5f;
+ array[3] = rng.nextFloat() + 0.5f;
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.setRotateM(array, 4, array[0], array[1], array[2], array[3]);
+ }
+ }
+
+ @Test
+ public void testSetRotateEulerM() {
+ Random rng = new Random();
+ array[0] = rng.nextFloat() * 90.0f;
+ array[1] = rng.nextFloat() * 90.0f;
+ array[2] = rng.nextFloat() * 90.0f;
+
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.setRotateEulerM(array, 3, array[0], array[1], array[2]);
+ }
+ }
+
+ @Test
+ public void testSetLookAtM() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Matrix.setLookAtM(array, 9,
+ 1.0f, 0.0f, 0.0f,
+ 1.0f, 0.0f, 1.0f,
+ 0.0f, 1.0f, 0.0f);
+ }
+ }
+}
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 0de0a1cf9c8e..d6b246a9e2e3 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -112,6 +112,7 @@ import android.text.TextUtils;
import android.text.format.DateFormat;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.LongArrayQueue;
@@ -2299,7 +2300,11 @@ public class AlarmManagerService extends SystemService {
+ " reached for uid: " + UserHandle.formatUid(callingUid)
+ ", callingPackage: " + callingPackage;
Slog.w(TAG, errorMsg);
- throw new IllegalStateException(errorMsg);
+ if (callingUid != Process.SYSTEM_UID) {
+ throw new IllegalStateException(errorMsg);
+ } else {
+ EventLog.writeEvent(0x534e4554, "234441463", -1, errorMsg);
+ }
}
setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation,
directReceiver, listenerTag, flags, workSource, alarmClock, callingUid,
diff --git a/api/Android.bp b/api/Android.bp
index 505d7bf99135..210b8f50b803 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -208,6 +208,24 @@ genrule {
}
genrule {
+ name: "sdk-annotations-module-lib.zip",
+ defaults: ["sdk-annotations-defaults"],
+ srcs: [
+ ":android-non-updatable-doc-stubs-module-lib{.annotations.zip}",
+ ":all-modules-module-lib-annotations",
+ ],
+}
+
+genrule {
+ name: "sdk-annotations-system-server.zip",
+ defaults: ["sdk-annotations-defaults"],
+ srcs: [
+ ":android-non-updatable-doc-stubs-system-server{.annotations.zip}",
+ ":all-modules-system-server-annotations",
+ ],
+}
+
+genrule {
name: "combined-removed-dex",
visibility: [
"//frameworks/base/boot",
diff --git a/api/api.go b/api/api.go
index f15804156bdf..6a6c493e041a 100644
--- a/api/api.go
+++ b/api/api.go
@@ -148,18 +148,35 @@ func createMergedStubsSrcjar(ctx android.LoadHookContext, modules []string) {
ctx.CreateModule(genrule.GenRuleFactory, &props)
}
-func createMergedPublicAnnotationsFilegroup(ctx android.LoadHookContext, modules []string) {
- props := fgProps{}
- props.Name = proptools.StringPtr("all-modules-public-annotations")
- props.Srcs = createSrcs(modules, "{.public.annotations.zip}")
- ctx.CreateModule(android.FileGroupFactory, &props)
-}
-
-func createMergedSystemAnnotationsFilegroup(ctx android.LoadHookContext, modules []string) {
- props := fgProps{}
- props.Name = proptools.StringPtr("all-modules-system-annotations")
- props.Srcs = createSrcs(modules, "{.system.annotations.zip}")
- ctx.CreateModule(android.FileGroupFactory, &props)
+func createMergedAnnotationsFilegroups(ctx android.LoadHookContext, modules, system_server_modules []string) {
+ for _, i := range []struct{
+ name string
+ tag string
+ modules []string
+ }{
+ {
+ name: "all-modules-public-annotations",
+ tag: "{.public.annotations.zip}",
+ modules: modules,
+ }, {
+ name: "all-modules-system-annotations",
+ tag: "{.system.annotations.zip}",
+ modules: modules,
+ }, {
+ name: "all-modules-module-lib-annotations",
+ tag: "{.module-lib.annotations.zip}",
+ modules: modules,
+ }, {
+ name: "all-modules-system-server-annotations",
+ tag: "{.system-server.annotations.zip}",
+ modules: system_server_modules,
+ },
+ } {
+ props := fgProps{}
+ props.Name = proptools.StringPtr(i.name)
+ props.Srcs = createSrcs(i.modules, i.tag)
+ ctx.CreateModule(android.FileGroupFactory, &props)
+ }
}
func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) {
@@ -172,17 +189,43 @@ func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) {
// difficult to achieve.
modules = remove(modules, art)
- props := genruleProps{}
- props.Name = proptools.StringPtr("api-versions-xml-public-filtered")
- props.Tools = []string{"api_versions_trimmer"}
- props.Out = []string{"api-versions-public-filtered.xml"}
- props.Cmd = proptools.StringPtr("$(location api_versions_trimmer) $(out) $(in)")
- // Note: order matters: first parameter is the full api-versions.xml
- // after that the stubs files in any order
- // stubs files are all modules that export API surfaces EXCEPT ART
- props.Srcs = append([]string{":api_versions_public{.api_versions.xml}"}, createSrcs(modules, ".stubs{.jar}")...)
- props.Dists = []android.Dist{{Targets: []string{"sdk"}}}
- ctx.CreateModule(genrule.GenRuleFactory, &props)
+ for _, i := range []struct{
+ name string
+ out string
+ in string
+ }{
+ {
+ // We shouldn't need public-filtered or system-filtered.
+ // public-filtered is currently used to lint things that
+ // use the module sdk or the system server sdk, but those
+ // should be switched over to module-filtered and
+ // system-server-filtered, and then public-filtered can
+ // be removed.
+ name: "api-versions-xml-public-filtered",
+ out: "api-versions-public-filtered.xml",
+ in: ":api_versions_public{.api_versions.xml}",
+ }, {
+ name: "api-versions-xml-module-lib-filtered",
+ out: "api-versions-module-lib-filtered.xml",
+ in: ":api_versions_module_lib{.api_versions.xml}",
+ }, {
+ name: "api-versions-xml-system-server-filtered",
+ out: "api-versions-system-server-filtered.xml",
+ in: ":api_versions_system_server{.api_versions.xml}",
+ },
+ } {
+ props := genruleProps{}
+ props.Name = proptools.StringPtr(i.name)
+ props.Out = []string{i.out}
+ // Note: order matters: first parameter is the full api-versions.xml
+ // after that the stubs files in any order
+ // stubs files are all modules that export API surfaces EXCEPT ART
+ props.Srcs = append([]string{i.in}, createSrcs(modules, ".stubs{.jar}")...)
+ props.Tools = []string{"api_versions_trimmer"}
+ props.Cmd = proptools.StringPtr("$(location api_versions_trimmer) $(out) $(in)")
+ props.Dists = []android.Dist{{Targets: []string{"sdk"}}}
+ ctx.CreateModule(genrule.GenRuleFactory, &props)
+ }
}
func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) {
@@ -279,11 +322,12 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_
func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
bootclasspath := a.properties.Bootclasspath
+ system_server_classpath := a.properties.System_server_classpath
if ctx.Config().VendorConfig("ANDROID").Bool("include_nonpublic_framework_api") {
bootclasspath = append(bootclasspath, a.properties.Conditional_bootclasspath...)
sort.Strings(bootclasspath)
}
- createMergedTxts(ctx, bootclasspath, a.properties.System_server_classpath)
+ createMergedTxts(ctx, bootclasspath, system_server_classpath)
createMergedStubsSrcjar(ctx, bootclasspath)
@@ -292,8 +336,7 @@ func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
createMergedFrameworkModuleLibStubs(ctx, bootclasspath)
createMergedFrameworkImpl(ctx, bootclasspath)
- createMergedPublicAnnotationsFilegroup(ctx, bootclasspath)
- createMergedSystemAnnotationsFilegroup(ctx, bootclasspath)
+ createMergedAnnotationsFilegroups(ctx, bootclasspath, system_server_classpath)
createFilteredApiVersions(ctx, bootclasspath)
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 836801deaa08..5af02f405ed9 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -52,11 +52,7 @@ enum {
#define SKIPPED_DUMPSTATE_SECTIONS { \
1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
1200, 1201, 1202, /* Native, hal, java traces */ \
- 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, \
- 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3027, 3028, 3029, \
- 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, \
- 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 4000, \
- 4001, /* Dumpsys */ }
+ 3018, /* dumpsys meminfo*/ }
namespace android {
namespace os {
diff --git a/core/api/current.txt b/core/api/current.txt
index 644a194f6ed1..9c7796ef9d4b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -4415,6 +4415,7 @@ package android.app {
method public void readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.ActivityManager.MemoryInfo> CREATOR;
+ field public long advertisedMem;
field public long availMem;
field public boolean lowMemory;
field public long threshold;
@@ -43490,7 +43491,7 @@ package android.telephony {
method public void registerTelephonyCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyCallback);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
- method @Nullable @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(int, @NonNull android.telephony.NetworkScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyScanManager.NetworkScanCallback);
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE}) public android.telephony.NetworkScan requestNetworkScan(int, @NonNull android.telephony.NetworkScanRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyScanManager.NetworkScanCallback);
method public void sendDialerSpecialCode(String);
method public String sendEnvelopeWithStatus(String);
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
diff --git a/core/java/android/accessibilityservice/OWNERS b/core/java/android/accessibilityservice/OWNERS
index a31cfae995b2..fb06e236dd8a 100644
--- a/core/java/android/accessibilityservice/OWNERS
+++ b/core/java/android/accessibilityservice/OWNERS
@@ -1,4 +1,6 @@
-svetoslavganov@google.com
pweaver@google.com
-rhedjao@google.com
ryanlwlin@google.com
+danielnorman@google.com
+sallyyuen@google.com
+aarmaly@google.com
+fuego@google.com
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index e6cdcc0ee742..0d6a07938e95 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -31,7 +31,6 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
-import java.util.Objects;
import java.util.Set;
/**
@@ -87,12 +86,6 @@ public class Account implements Parcelable {
if (TextUtils.isEmpty(type)) {
throw new IllegalArgumentException("the type must not be empty: " + type);
}
- if (name.length() > 200) {
- throw new IllegalArgumentException("account name is longer than 200 characters");
- }
- if (type.length() > 200) {
- throw new IllegalArgumentException("account type is longer than 200 characters");
- }
this.name = name;
this.type = type;
this.accessId = accessId;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5d1d225f4d2d..6f9a98d8313f 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -29,6 +29,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
@@ -2813,6 +2814,15 @@ public class ActivityManager {
*/
public static class MemoryInfo implements Parcelable {
/**
+ * The advertised memory of the system, as the end user would encounter in a retail display
+ * environment. This value might be different from {@code totalMem}. This could be due to
+ * many reasons. For example, the ODM could reserve part of the memory for the Trusted
+ * Execution Environment (TEE) which the kernel doesn't have access or knowledge about it.
+ */
+ @SuppressLint("MutableBareField")
+ public long advertisedMem;
+
+ /**
* The available memory on the system. This number should not
* be considered absolute: due to the nature of the kernel, a significant
* portion of this memory is actually in use and needed for the overall
@@ -2861,6 +2871,7 @@ public class ActivityManager {
}
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(advertisedMem);
dest.writeLong(availMem);
dest.writeLong(totalMem);
dest.writeLong(threshold);
@@ -2872,6 +2883,7 @@ public class ActivityManager {
}
public void readFromParcel(Parcel source) {
+ advertisedMem = source.readLong();
availMem = source.readLong();
totalMem = source.readLong();
threshold = source.readLong();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 9c0b443bb3c7..07fbde546cbc 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1454,6 +1454,11 @@ public class ActivityOptions extends ComponentOptions {
}
/** @hide */
+ public void setRemoteTransition(@Nullable RemoteTransition remoteTransition) {
+ mRemoteTransition = remoteTransition;
+ }
+
+ /** @hide */
public static ActivityOptions fromBundle(Bundle bOptions) {
return bOptions != null ? new ActivityOptions(bOptions) : null;
}
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index 068304d75910..f3fc46869916 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -29,7 +29,7 @@ per-file ProfilerInfo* = file:/services/core/java/com/android/server/am/OWNERS
per-file Service* = file:/services/core/java/com/android/server/am/OWNERS
per-file SystemServiceRegistry.java = file:/services/core/java/com/android/server/am/OWNERS
per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS
-per-file UiAutomation.java = file:/services/accessibility/OWNERS
+per-file UiAutomation* = file:/services/accessibility/OWNERS
per-file GameManager* = file:/GAME_MANAGER_OWNERS
per-file GameState* = file:/GAME_MANAGER_OWNERS
per-file IGameManager* = file:/GAME_MANAGER_OWNERS
diff --git a/core/java/android/companion/OWNERS b/core/java/android/companion/OWNERS
index 004f66caed7b..0348fe2776fe 100644
--- a/core/java/android/companion/OWNERS
+++ b/core/java/android/companion/OWNERS
@@ -1,5 +1,3 @@
-ewol@google.com
evanxinchen@google.com
guojing@google.com
-svetoslavganov@google.com
-sergeynv@google.com \ No newline at end of file
+raphk@google.com \ No newline at end of file
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index 830584314039..bc6368639baa 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -299,7 +299,7 @@ public final class SQLiteDatabaseConfiguration {
if (isLegacyCompatibilityWalEnabled()) {
return SQLiteCompatibilityWalFlags.getWALSyncMode();
} else {
- return SQLiteGlobal.getDefaultSyncMode();
+ return SQLiteGlobal.getWALSyncMode();
}
} else {
return SQLiteGlobal.getDefaultSyncMode();
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 0f1b39c01289..17dcc80dd797 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -826,7 +826,9 @@ public abstract class CameraDevice implements AutoCloseable {
* <p> Here, SC Map, refers to the {@link StreamConfigurationMap}, the target stream sizes must
* be chosen from. {@code DEFAULT} refers to the default sensor pixel mode {@link
* StreamConfigurationMap} and {@code MAX_RES} refers to the maximum resolution {@link
- * StreamConfigurationMap}. The same capture request must not mix targets from
+ * StreamConfigurationMap}. For {@code MAX_RES} streams, {@code MAX} in the {@code Max size} column refers to the maximum size from
+ * {@link StreamConfigurationMap#getOutputSizes} and {@link StreamConfigurationMap#getHighResolutionOutputSizes}.
+ * Note: The same capture request must not mix targets from
* {@link StreamConfigurationMap}s corresponding to different sensor pixel modes. </p>
*
* <p> 10-bit output capable
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index e5b9cdb74d3b..956a474401ba 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -1723,7 +1723,17 @@ public final class MandatoryStreamCombination {
}
if (isUltraHighResolution) {
- sizes.add(getMaxSize(sm.getOutputSizes(formatChosen)));
+ Size [] outputSizes = sm.getOutputSizes(formatChosen);
+ Size [] highResolutionOutputSizes =
+ sm.getHighResolutionOutputSizes(formatChosen);
+ Size maxBurstSize = getMaxSizeOrNull(outputSizes);
+ Size maxHighResolutionSize = getMaxSizeOrNull(highResolutionOutputSizes);
+ Size chosenMaxSize =
+ maxBurstSize != null ? maxBurstSize : maxHighResolutionSize;
+ if (maxBurstSize != null && maxHighResolutionSize != null) {
+ chosenMaxSize = getMaxSize(maxBurstSize, maxHighResolutionSize);
+ }
+ sizes.add(chosenMaxSize);
} else {
if (formatChosen == ImageFormat.RAW_SENSOR) {
// RAW_SENSOR always has MAXIMUM threshold.
@@ -2126,6 +2136,21 @@ public final class MandatoryStreamCombination {
}
/**
+ * Get the largest size by area.
+ *
+ * @param sizes an array of sizes
+ *
+ * @return Largest Size or null if sizes was null or had 0 elements
+ */
+ public static @Nullable Size getMaxSizeOrNull(Size... sizes) {
+ if (sizes == null || sizes.length == 0) {
+ return null;
+ }
+
+ return getMaxSize(sizes);
+ }
+
+ /**
* Whether or not the hardware level reported by android.info.supportedHardwareLevel is
* at least the desired one (but could be higher)
*/
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 2b34d8639235..0b56d19201fb 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -209,7 +209,8 @@ public final class CardEmulation {
*/
public boolean isDefaultServiceForCategory(ComponentName service, String category) {
try {
- return sService.isDefaultServiceForCategory(mContext.getUserId(), service, category);
+ return sService.isDefaultServiceForCategory(mContext.getUser().getIdentifier(),
+ service, category);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -218,8 +219,8 @@ public final class CardEmulation {
return false;
}
try {
- return sService.isDefaultServiceForCategory(mContext.getUserId(), service,
- category);
+ return sService.isDefaultServiceForCategory(mContext.getUser().getIdentifier(),
+ service, category);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover CardEmulationService.");
return false;
@@ -240,7 +241,8 @@ public final class CardEmulation {
*/
public boolean isDefaultServiceForAid(ComponentName service, String aid) {
try {
- return sService.isDefaultServiceForAid(mContext.getUserId(), service, aid);
+ return sService.isDefaultServiceForAid(mContext.getUser().getIdentifier(),
+ service, aid);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -249,7 +251,8 @@ public final class CardEmulation {
return false;
}
try {
- return sService.isDefaultServiceForAid(mContext.getUserId(), service, aid);
+ return sService.isDefaultServiceForAid(mContext.getUser().getIdentifier(),
+ service, aid);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return false;
@@ -348,7 +351,8 @@ public final class CardEmulation {
List<String> aids) {
AidGroup aidGroup = new AidGroup(aids, category);
try {
- return sService.registerAidGroupForService(mContext.getUserId(), service, aidGroup);
+ return sService.registerAidGroupForService(mContext.getUser().getIdentifier(),
+ service, aidGroup);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -357,8 +361,8 @@ public final class CardEmulation {
return false;
}
try {
- return sService.registerAidGroupForService(mContext.getUserId(), service,
- aidGroup);
+ return sService.registerAidGroupForService(mContext.getUser().getIdentifier(),
+ service, aidGroup);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return false;
@@ -391,7 +395,7 @@ public final class CardEmulation {
}
try {
- return sService.unsetOffHostForService(mContext.getUserId(), service);
+ return sService.unsetOffHostForService(mContext.getUser().getIdentifier(), service);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -400,7 +404,7 @@ public final class CardEmulation {
return false;
}
try {
- return sService.unsetOffHostForService(mContext.getUserId(), service);
+ return sService.unsetOffHostForService(mContext.getUser().getIdentifier(), service);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return false;
@@ -468,7 +472,7 @@ public final class CardEmulation {
}
try {
- return sService.setOffHostForService(mContext.getUserId(), service,
+ return sService.setOffHostForService(mContext.getUser().getIdentifier(), service,
offHostSecureElement);
} catch (RemoteException e) {
// Try one more time
@@ -478,7 +482,7 @@ public final class CardEmulation {
return false;
}
try {
- return sService.setOffHostForService(mContext.getUserId(), service,
+ return sService.setOffHostForService(mContext.getUser().getIdentifier(), service,
offHostSecureElement);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
@@ -503,8 +507,8 @@ public final class CardEmulation {
*/
public List<String> getAidsForService(ComponentName service, String category) {
try {
- AidGroup group = sService.getAidGroupForService(mContext.getUserId(), service,
- category);
+ AidGroup group = sService.getAidGroupForService(mContext.getUser().getIdentifier(),
+ service, category);
return (group != null ? group.getAids() : null);
} catch (RemoteException e) {
recoverService();
@@ -513,8 +517,8 @@ public final class CardEmulation {
return null;
}
try {
- AidGroup group = sService.getAidGroupForService(mContext.getUserId(), service,
- category);
+ AidGroup group = sService.getAidGroupForService(mContext.getUser().getIdentifier(),
+ service, category);
return (group != null ? group.getAids() : null);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover CardEmulationService.");
@@ -540,7 +544,8 @@ public final class CardEmulation {
*/
public boolean removeAidsForService(ComponentName service, String category) {
try {
- return sService.removeAidGroupForService(mContext.getUserId(), service, category);
+ return sService.removeAidGroupForService(mContext.getUser().getIdentifier(), service,
+ category);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -549,7 +554,8 @@ public final class CardEmulation {
return false;
}
try {
- return sService.removeAidGroupForService(mContext.getUserId(), service, category);
+ return sService.removeAidGroupForService(mContext.getUser().getIdentifier(),
+ service, category);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return false;
@@ -684,7 +690,8 @@ public final class CardEmulation {
@Nullable
public List<String> getAidsForPreferredPaymentService() {
try {
- ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+ ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(
+ mContext.getUser().getIdentifier());
return (serviceInfo != null ? serviceInfo.getAids() : null);
} catch (RemoteException e) {
recoverService();
@@ -694,7 +701,7 @@ public final class CardEmulation {
}
try {
ApduServiceInfo serviceInfo =
- sService.getPreferredPaymentService(mContext.getUserId());
+ sService.getPreferredPaymentService(mContext.getUser().getIdentifier());
return (serviceInfo != null ? serviceInfo.getAids() : null);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover CardEmulationService.");
@@ -723,7 +730,8 @@ public final class CardEmulation {
@Nullable
public String getRouteDestinationForPreferredPaymentService() {
try {
- ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+ ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(
+ mContext.getUser().getIdentifier());
if (serviceInfo != null) {
if (!serviceInfo.isOnHost()) {
return serviceInfo.getOffHostSecureElement() == null ?
@@ -740,7 +748,7 @@ public final class CardEmulation {
}
try {
ApduServiceInfo serviceInfo =
- sService.getPreferredPaymentService(mContext.getUserId());
+ sService.getPreferredPaymentService(mContext.getUser().getIdentifier());
if (serviceInfo != null) {
if (!serviceInfo.isOnHost()) {
return serviceInfo.getOffHostSecureElement() == null ?
@@ -766,7 +774,8 @@ public final class CardEmulation {
@Nullable
public CharSequence getDescriptionForPreferredPaymentService() {
try {
- ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(mContext.getUserId());
+ ApduServiceInfo serviceInfo = sService.getPreferredPaymentService(
+ mContext.getUser().getIdentifier());
return (serviceInfo != null ? serviceInfo.getDescription() : null);
} catch (RemoteException e) {
recoverService();
@@ -776,7 +785,7 @@ public final class CardEmulation {
}
try {
ApduServiceInfo serviceInfo =
- sService.getPreferredPaymentService(mContext.getUserId());
+ sService.getPreferredPaymentService(mContext.getUser().getIdentifier());
return (serviceInfo != null ? serviceInfo.getDescription() : null);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to recover CardEmulationService.");
@@ -790,7 +799,8 @@ public final class CardEmulation {
*/
public boolean setDefaultServiceForCategory(ComponentName service, String category) {
try {
- return sService.setDefaultServiceForCategory(mContext.getUserId(), service, category);
+ return sService.setDefaultServiceForCategory(mContext.getUser().getIdentifier(),
+ service, category);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -799,8 +809,8 @@ public final class CardEmulation {
return false;
}
try {
- return sService.setDefaultServiceForCategory(mContext.getUserId(), service,
- category);
+ return sService.setDefaultServiceForCategory(mContext.getUser().getIdentifier(),
+ service, category);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return false;
@@ -813,7 +823,7 @@ public final class CardEmulation {
*/
public boolean setDefaultForNextTap(ComponentName service) {
try {
- return sService.setDefaultForNextTap(mContext.getUserId(), service);
+ return sService.setDefaultForNextTap(mContext.getUser().getIdentifier(), service);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -822,7 +832,7 @@ public final class CardEmulation {
return false;
}
try {
- return sService.setDefaultForNextTap(mContext.getUserId(), service);
+ return sService.setDefaultForNextTap(mContext.getUser().getIdentifier(), service);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return false;
@@ -857,7 +867,7 @@ public final class CardEmulation {
*/
public List<ApduServiceInfo> getServices(String category) {
try {
- return sService.getServices(mContext.getUserId(), category);
+ return sService.getServices(mContext.getUser().getIdentifier(), category);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -866,7 +876,7 @@ public final class CardEmulation {
return null;
}
try {
- return sService.getServices(mContext.getUserId(), category);
+ return sService.getServices(mContext.getUser().getIdentifier(), category);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return null;
diff --git a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
index 557e41a2b103..3c924556365e 100644
--- a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
+++ b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
@@ -117,7 +117,7 @@ public final class NfcFCardEmulation {
throw new NullPointerException("service is null");
}
try {
- return sService.getSystemCodeForService(mContext.getUserId(), service);
+ return sService.getSystemCodeForService(mContext.getUser().getIdentifier(), service);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -126,7 +126,8 @@ public final class NfcFCardEmulation {
return null;
}
try {
- return sService.getSystemCodeForService(mContext.getUserId(), service);
+ return sService.getSystemCodeForService(mContext.getUser().getIdentifier(),
+ service);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
ee.rethrowAsRuntimeException();
@@ -163,7 +164,7 @@ public final class NfcFCardEmulation {
throw new NullPointerException("service or systemCode is null");
}
try {
- return sService.registerSystemCodeForService(mContext.getUserId(),
+ return sService.registerSystemCodeForService(mContext.getUser().getIdentifier(),
service, systemCode);
} catch (RemoteException e) {
// Try one more time
@@ -173,7 +174,7 @@ public final class NfcFCardEmulation {
return false;
}
try {
- return sService.registerSystemCodeForService(mContext.getUserId(),
+ return sService.registerSystemCodeForService(mContext.getUser().getIdentifier(),
service, systemCode);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
@@ -194,7 +195,7 @@ public final class NfcFCardEmulation {
throw new NullPointerException("service is null");
}
try {
- return sService.removeSystemCodeForService(mContext.getUserId(), service);
+ return sService.removeSystemCodeForService(mContext.getUser().getIdentifier(), service);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -203,7 +204,8 @@ public final class NfcFCardEmulation {
return false;
}
try {
- return sService.removeSystemCodeForService(mContext.getUserId(), service);
+ return sService.removeSystemCodeForService(mContext.getUser().getIdentifier(),
+ service);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
ee.rethrowAsRuntimeException();
@@ -229,7 +231,7 @@ public final class NfcFCardEmulation {
throw new NullPointerException("service is null");
}
try {
- return sService.getNfcid2ForService(mContext.getUserId(), service);
+ return sService.getNfcid2ForService(mContext.getUser().getIdentifier(), service);
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -238,7 +240,7 @@ public final class NfcFCardEmulation {
return null;
}
try {
- return sService.getNfcid2ForService(mContext.getUserId(), service);
+ return sService.getNfcid2ForService(mContext.getUser().getIdentifier(), service);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
ee.rethrowAsRuntimeException();
@@ -272,7 +274,7 @@ public final class NfcFCardEmulation {
throw new NullPointerException("service or nfcid2 is null");
}
try {
- return sService.setNfcid2ForService(mContext.getUserId(),
+ return sService.setNfcid2ForService(mContext.getUser().getIdentifier(),
service, nfcid2);
} catch (RemoteException e) {
// Try one more time
@@ -282,7 +284,7 @@ public final class NfcFCardEmulation {
return false;
}
try {
- return sService.setNfcid2ForService(mContext.getUserId(),
+ return sService.setNfcid2ForService(mContext.getUser().getIdentifier(),
service, nfcid2);
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
@@ -380,7 +382,7 @@ public final class NfcFCardEmulation {
*/
public List<NfcFServiceInfo> getNfcFServices() {
try {
- return sService.getNfcFServices(mContext.getUserId());
+ return sService.getNfcFServices(mContext.getUser().getIdentifier());
} catch (RemoteException e) {
// Try one more time
recoverService();
@@ -389,7 +391,7 @@ public final class NfcFCardEmulation {
return null;
}
try {
- return sService.getNfcFServices(mContext.getUserId());
+ return sService.getNfcFServices(mContext.getUser().getIdentifier());
} catch (RemoteException ee) {
Log.e(TAG, "Failed to reach CardEmulationService.");
return null;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index edfcb3d6f12a..d5c3de146015 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -54,6 +54,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.system.StructStat;
import android.text.TextUtils;
+import android.util.DataUnit;
import android.util.Log;
import android.util.Slog;
import android.webkit.MimeTypeMap;
@@ -83,6 +84,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -1309,6 +1311,85 @@ public final class FileUtils {
return val * pow;
}
+ private static long toBytes(long value, String unit) {
+ unit = unit.toUpperCase();
+
+ if (List.of("B").contains(unit)) {
+ return value;
+ }
+
+ if (List.of("K", "KB").contains(unit)) {
+ return DataUnit.KILOBYTES.toBytes(value);
+ }
+
+ if (List.of("M", "MB").contains(unit)) {
+ return DataUnit.MEGABYTES.toBytes(value);
+ }
+
+ if (List.of("G", "GB").contains(unit)) {
+ return DataUnit.GIGABYTES.toBytes(value);
+ }
+
+ if (List.of("KI", "KIB").contains(unit)) {
+ return DataUnit.KIBIBYTES.toBytes(value);
+ }
+
+ if (List.of("MI", "MIB").contains(unit)) {
+ return DataUnit.MEBIBYTES.toBytes(value);
+ }
+
+ if (List.of("GI", "GIB").contains(unit)) {
+ return DataUnit.GIBIBYTES.toBytes(value);
+ }
+
+ return Long.MIN_VALUE;
+ }
+
+ /**
+ * @param fmtSize The string that contains the size to be parsed. The
+ * expected format is:
+ *
+ * <p>"^((\\s*[-+]?[0-9]+)\\s*(B|K|KB|M|MB|G|GB|Ki|KiB|Mi|MiB|Gi|GiB)\\s*)$"
+ *
+ * <p>For example: 10Kb, 500GiB, 100mb. The unit is not case sensitive.
+ *
+ * @return the size in bytes. If {@code fmtSize} has invalid format, it
+ * returns {@link Long#MIN_VALUE}.
+ * @hide
+ */
+ public static long parseSize(@Nullable String fmtSize) {
+ if (fmtSize == null || fmtSize.isBlank()) {
+ return Long.MIN_VALUE;
+ }
+
+ int sign = 1;
+ fmtSize = fmtSize.trim();
+ char first = fmtSize.charAt(0);
+ if (first == '-' || first == '+') {
+ if (first == '-') {
+ sign = -1;
+ }
+
+ fmtSize = fmtSize.replace(first + "", "");
+ }
+
+ int index = 0;
+ // Find the last index of the value in fmtSize.
+ while (index < fmtSize.length() && Character.isDigit(fmtSize.charAt(index))) {
+ index++;
+ }
+
+ // Check if number and units are present.
+ if (index == 0 || index == fmtSize.length()) {
+ return Long.MIN_VALUE;
+ }
+
+ long value = sign * Long.valueOf(fmtSize.substring(0, index));
+ String unit = fmtSize.substring(index).trim();
+
+ return toBytes(value, unit);
+ }
+
/**
* Closes the given object quietly, ignoring any checked exceptions. Does
* nothing if the given object is {@code null}.
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 56652f57e6f1..a6ae663dabb0 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -560,7 +560,9 @@ public final class Parcel {
*/
public final void recycle() {
if (mRecycled) {
- Log.w(TAG, "Recycle called on unowned Parcel. (recycle twice?)", mStack);
+ Log.w(TAG, "Recycle called on unowned Parcel. (recycle twice?) Here: "
+ + Log.getStackTraceString(new Throwable())
+ + " Original recycle call (if DEBUG_RECYCLE): ", mStack);
}
mRecycled = true;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index e06e7326a860..b3afaecca849 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -26,6 +26,7 @@ import android.annotation.TestApi;
import android.annotation.UptimeMillisLong;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build.VERSION_CODES;
+import android.sysprop.MemoryProperties;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -1336,6 +1337,24 @@ public class Process {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public static final native void sendSignalQuiet(int pid, int signal);
+ /**
+ * @return The advertised memory of the system, as the end user would encounter in a retail
+ * display environment. If the advertised memory is not defined, it returns
+ * {@code getTotalMemory()} rounded.
+ *
+ * @hide
+ */
+ public static final long getAdvertisedMem() {
+ String formatSize = MemoryProperties.memory_ddr_size().orElse("0KB");
+ long memSize = FileUtils.parseSize(formatSize);
+
+ if (memSize == Long.MIN_VALUE) {
+ return FileUtils.roundStorageSize(getTotalMemory());
+ }
+
+ return memSize;
+ }
+
/** @hide */
@UnsupportedAppUsage
public static final native long getFreeMemory();
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 7b9ef726b1a3..466ac7895710 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -377,6 +377,14 @@ public final class DeviceConfig {
public static final String NAMESPACE_REBOOT_READINESS = "reboot_readiness";
/**
+ * Namespace for Remote Key Provisioning related features.
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_REMOTE_KEY_PROVISIONING_NATIVE =
+ "remote_key_provisioning_native";
+
+ /**
* Namespace for Rollback flags that are applied immediately.
*
* @hide
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 8efc5eb6b6ff..e720f1ab1523 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -65,6 +65,7 @@ public final class KeymasterDefs {
public static final int KM_TAG_PADDING = Tag.PADDING; // KM_ENUM_REP | 6;
public static final int KM_TAG_CALLER_NONCE = Tag.CALLER_NONCE; // KM_BOOL | 7;
public static final int KM_TAG_MIN_MAC_LENGTH = Tag.MIN_MAC_LENGTH; // KM_UINT | 8;
+ public static final int KM_TAG_EC_CURVE = Tag.EC_CURVE; // KM_ENUM | 10;
public static final int KM_TAG_RSA_PUBLIC_EXPONENT = Tag.RSA_PUBLIC_EXPONENT; // KM_ULONG | 200;
public static final int KM_TAG_INCLUDE_UNIQUE_ID = Tag.INCLUDE_UNIQUE_ID; // KM_BOOL | 202;
diff --git a/core/java/android/service/resumeonreboot/OWNERS b/core/java/android/service/resumeonreboot/OWNERS
index 721fbaf2d4ed..e09805310bbb 100644
--- a/core/java/android/service/resumeonreboot/OWNERS
+++ b/core/java/android/service/resumeonreboot/OWNERS
@@ -1 +1,2 @@
-ejyzhang@google.com \ No newline at end of file
+aveena@google.com
+ejyzhang@google.com
diff --git a/core/java/android/text/OWNERS b/core/java/android/text/OWNERS
index 0b51b2d90b79..a6be687ab4c9 100644
--- a/core/java/android/text/OWNERS
+++ b/core/java/android/text/OWNERS
@@ -1,4 +1,10 @@
set noparent
+halilibo@google.com
+haoyuchang@google.com
+justinghan@google.com
+klippenstein@google.com
+nona@google.com
+seanmcq@google.com
siyamed@google.com
-nona@google.com \ No newline at end of file
+soboleva@google.com
diff --git a/core/java/android/view/accessibility/OWNERS b/core/java/android/view/accessibility/OWNERS
index b1d3967a8b04..73d134146c3f 100644
--- a/core/java/android/view/accessibility/OWNERS
+++ b/core/java/android/view/accessibility/OWNERS
@@ -10,3 +10,7 @@ ogunwale@google.com
jjaggi@google.com
pweaver@google.com
ryanlwlin@google.com
+danielnorman@google.com
+sallyyuen@google.com
+aarmaly@google.com
+fuego@google.com
diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS
index 56310aef7752..02dafd44d3bd 100644
--- a/core/java/android/widget/OWNERS
+++ b/core/java/android/widget/OWNERS
@@ -8,8 +8,8 @@ siyamed@google.com
mount@google.com
njawad@google.com
-per-file TextView*,EditText.java,Editor.java,EditorTouchState.java = file:../text/OWNERS
+per-file TextView*,Edit*,Selection* = file:../text/OWNERS
per-file SpellChecker.java = file:../view/inputmethod/OWNERS
-per-file RemoteViews* = file:../appwidget/OWNERS \ No newline at end of file
+per-file RemoteViews* = file:../appwidget/OWNERS
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2879cd888d2d..bc7e31fac222 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1598,7 +1598,13 @@ public class RemoteViews implements Parcelable, Filter {
public BitmapCache(Parcel source) {
mBitmaps = source.createTypedArrayList(Bitmap.CREATOR);
- mBitmapHashes = source.readSparseIntArray();
+ mBitmapHashes = new SparseIntArray();
+ for (int i = 0; i < mBitmaps.size(); i++) {
+ Bitmap b = mBitmaps.get(i);
+ if (b != null) {
+ mBitmapHashes.put(b.hashCode(), i);
+ }
+ }
}
public int getBitmapId(Bitmap b) {
@@ -1614,7 +1620,7 @@ public class RemoteViews implements Parcelable, Filter {
b = b.asShared();
}
mBitmaps.add(b);
- mBitmapHashes.put(mBitmaps.size() - 1, hash);
+ mBitmapHashes.put(hash, mBitmaps.size() - 1);
mBitmapMemory = -1;
return (mBitmaps.size() - 1);
}
@@ -1631,7 +1637,6 @@ public class RemoteViews implements Parcelable, Filter {
public void writeBitmapsToParcel(Parcel dest, int flags) {
dest.writeTypedList(mBitmaps, flags);
- dest.writeSparseIntArray(mBitmapHashes);
}
public int getBitmapMemory() {
diff --git a/core/java/com/android/internal/accessibility/OWNERS b/core/java/com/android/internal/accessibility/OWNERS
index b3c09e9d539a..0955e005791e 100644
--- a/core/java/com/android/internal/accessibility/OWNERS
+++ b/core/java/com/android/internal/accessibility/OWNERS
@@ -1,4 +1,6 @@
# Bug component: 44214
-svetoslavganov@google.com
pweaver@google.com
-qasid@google.com
+danielnorman@google.com
+sallyyuen@google.com
+aarmaly@google.com
+fuego@google.com
diff --git a/core/java/com/android/internal/display/BrightnessSynchronizer.java b/core/java/com/android/internal/display/BrightnessSynchronizer.java
index 627631a376f7..62c7966bb2d6 100644
--- a/core/java/com/android/internal/display/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/display/BrightnessSynchronizer.java
@@ -115,7 +115,7 @@ public class BrightnessSynchronizer {
Slog.i(TAG, "Setting initial brightness to default value of: " + defaultBrightness);
}
- mBrightnessSyncObserver.startObserving();
+ mBrightnessSyncObserver.startObserving(mHandler);
mHandler.sendEmptyMessageAtTime(MSG_RUN_UPDATE, mClock.uptimeMillis());
}
@@ -482,27 +482,29 @@ public class BrightnessSynchronizer {
}
};
- private final ContentObserver mContentObserver = new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (selfChange) {
- return;
- }
- if (BRIGHTNESS_URI.equals(uri)) {
- handleBrightnessChangeInt(getScreenBrightnessInt());
+ private ContentObserver createBrightnessContentObserver(Handler handler) {
+ return new ContentObserver(handler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (selfChange) {
+ return;
+ }
+ if (BRIGHTNESS_URI.equals(uri)) {
+ handleBrightnessChangeInt(getScreenBrightnessInt());
+ }
}
- }
- };
+ };
+ }
boolean isObserving() {
return mIsObserving;
}
- void startObserving() {
+ void startObserving(Handler handler) {
final ContentResolver cr = mContext.getContentResolver();
- cr.registerContentObserver(BRIGHTNESS_URI, false, mContentObserver,
- UserHandle.USER_ALL);
- mDisplayManager.registerDisplayListener(mListener, mHandler,
+ cr.registerContentObserver(BRIGHTNESS_URI, false,
+ createBrightnessContentObserver(handler), UserHandle.USER_ALL);
+ mDisplayManager.registerDisplayListener(mListener, handler,
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
mIsObserving = true;
}
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index b866723954b5..b11ea2961c17 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -25,6 +25,7 @@ import android.graphics.ImageDecoder;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Size;
@@ -108,6 +109,12 @@ public class LocalImageResolver {
}
break;
case Icon.TYPE_RESOURCE:
+ if (!(TextUtils.isEmpty(icon.getResPackage())
+ || context.getPackageName().equals(icon.getResPackage()))) {
+ // We can't properly resolve icons from other packages here, so fall back.
+ return icon.loadDrawable(context);
+ }
+
Drawable result = resolveImage(icon.getResId(), context, maxWidth, maxHeight);
if (result != null) {
return tintDrawable(icon, result);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 88aa4de0db24..77317d1c3c1a 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -2179,7 +2179,7 @@ static jint convertAudioMixToNative(JNIEnv *env,
break;
}
- nAudioMix->mCriteria.add(nCriterion);
+ nAudioMix->mCriteria.push_back(nCriterion);
env->DeleteLocalRef(jCriterion);
}
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index bb4ab39a59d1..1f64df49cb56 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -101,9 +101,18 @@ static void android_os_Parcel_markSensitive(jlong nativePtr)
static void android_os_Parcel_markForBinder(JNIEnv* env, jclass clazz, jlong nativePtr,
jobject binder)
{
+ LOG_ALWAYS_FATAL_IF(binder == nullptr, "Null binder specified for markForBinder");
+
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel) {
- parcel->markForBinder(ibinderForJavaObject(env, binder));
+ sp<IBinder> nBinder = ibinderForJavaObject(env, binder);
+
+ if (nBinder == nullptr) {
+ ALOGE("Native binder in markForBinder is null for non-null jobject");
+ return;
+ }
+
+ parcel->markForBinder(nBinder);
}
}
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index f28e2f636dac..9f88f3369ae8 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -798,6 +798,12 @@ sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);
+
+ if (jbh == nullptr) {
+ ALOGE("JavaBBinderHolder null on binder");
+ return nullptr;
+ }
+
return jbh->get(env, obj);
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d689aab96ce9..6f83ab169b5f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1995,6 +1995,9 @@
on grouped devices. -->
<bool name="config_volumeAdjustmentForRemoteGroupSessions">true</bool>
+ <!-- Flag indicating current media Output Switcher version. -->
+ <integer name="config_mediaOutputSwitchDialogVersion">1</integer>
+
<!-- Flag indicating that an outbound call must have a call capable phone account
that has declared it can process the call's handle. -->
<bool name="config_requireCallCapableAccountForHandle">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 234c43525a01..1f71bf9f95dd 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4703,6 +4703,8 @@
<java-symbol type="bool" name="config_volumeAdjustmentForRemoteGroupSessions" />
+ <java-symbol type="integer" name="config_mediaOutputSwitchDialogVersion" />
+
<!-- List of shared library packages that should be loaded by the classloader after the
code and resources provided by applications. -->
<java-symbol type="array" name="config_sharedLibrariesLoadedAfterApp" />
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index c1e72fe75666..5f731e201866 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -58,10 +58,10 @@ import android.provider.DocumentsContract.Document;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
-import libcore.io.Streams;
-
import com.google.android.collect.Sets;
+import libcore.io.Streams;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -524,6 +524,56 @@ public class FileUtilsTest {
}
@Test
+ public void testParseSize() {
+ assertEquals(0L, FileUtils.parseSize("0MB"));
+ assertEquals(1_024L, FileUtils.parseSize("1024b"));
+ assertEquals(-1L, FileUtils.parseSize(" -1 b "));
+ assertEquals(0L, FileUtils.parseSize(" -0 gib "));
+ assertEquals(1_000L, FileUtils.parseSize("1K"));
+ assertEquals(1_000L, FileUtils.parseSize("1KB"));
+ assertEquals(10_000L, FileUtils.parseSize("10KB"));
+ assertEquals(100_000L, FileUtils.parseSize("100KB"));
+ assertEquals(1_000_000L, FileUtils.parseSize("1000KB"));
+ assertEquals(1_024_000L, FileUtils.parseSize("1000KiB"));
+ assertEquals(70_000_000L, FileUtils.parseSize("070M"));
+ assertEquals(70_000_000L, FileUtils.parseSize("070MB"));
+ assertEquals(73_400_320L, FileUtils.parseSize("70MiB"));
+ assertEquals(700_000_000L, FileUtils.parseSize("700000KB"));
+ assertEquals(200_000_000L, FileUtils.parseSize("+200MB"));
+ assertEquals(1_000_000_000L, FileUtils.parseSize("1000MB"));
+ assertEquals(1_000_000_000L, FileUtils.parseSize("+1000 mb"));
+ assertEquals(644_245_094_400L, FileUtils.parseSize("600GiB"));
+ assertEquals(999_000_000_000L, FileUtils.parseSize("999GB"));
+ assertEquals(999_000_000_000L, FileUtils.parseSize("999 gB"));
+ assertEquals(9_999_000_000_000L, FileUtils.parseSize("9999GB"));
+ assertEquals(9_000_000_000_000L, FileUtils.parseSize(" 9000 GB "));
+ assertEquals(1_234_000_000_000L, FileUtils.parseSize(" 1234 GB "));
+ assertEquals(1_234_567_890_000L, FileUtils.parseSize(" 1234567890 KB "));
+ }
+
+ @Test
+ public void testParseSize_invalidArguments() {
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize(null));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("null"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize(""));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" "));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("KB"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("123 dd"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("Invalid"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" ABC890 KB "));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("-=+90 KB "));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("123"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("--123"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("-KB"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("++123"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+ 1 +"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("+--+ 1 +"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize("1GB+"));
+ assertEquals(Long.MIN_VALUE, FileUtils.parseSize(" + 1234567890 KB "));
+ }
+
+ @Test
public void testTranslateMode() throws Exception {
assertTranslate("r", O_RDONLY, MODE_READ_ONLY);
diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java
index ae4edb97aab0..52846dfbb14b 100644
--- a/core/tests/coretests/src/android/os/ProcessTest.java
+++ b/core/tests/coretests/src/android/os/ProcessTest.java
@@ -72,4 +72,7 @@ public class ProcessTest extends TestCase {
assertEquals(-1, Process.getThreadGroupLeader(BAD_PID));
}
+ public void testGetAdvertisedMem() {
+ assertTrue(Process.getTotalMemory() <= Process.getAdvertisedMem());
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
index c63d18bfa531..0cee526651a6 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
@@ -270,4 +270,13 @@ public class LocalImageResolverTest {
assertThat(bd.getBitmap().getHeight()).isEqualTo(originalHeight);
}
+
+ @Test
+ public void resolveImage_iconWithOtherPackageResource_usesPackageContextDefinition()
+ throws IOException {
+ Icon icon = Icon.createWithResource("this_is_invalid", R.drawable.test32x24);
+ Drawable d = LocalImageResolver.resolveImage(icon, mContext);
+ // This drawable must not be loaded - if it was, the code ignored the package specification.
+ assertThat(d).isNull();
+ }
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 392d89e4fc6a..8ca16071a1e4 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -483,6 +483,8 @@ applications that come with the platform
<permission name="android.permission.NOTIFY_PENDING_SYSTEM_UPDATE" />
<!-- Permission required for GTS test - GtsAssistIntentTestCases -->
<permission name="android.permission.MANAGE_VOICE_KEYPHRASES" />
+ <!-- Permission required for test - CellBroadcastComplianceTest -->
+ <permission name="com.android.cellbroadcastservice.FULL_ACCESS_CELL_BROADCAST_HISTORY" />
<!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
<permission name="android.permission.LOCK_DEVICE" />
<!-- Permissions required for CTS test - CtsSafetyCenterTestCases -->
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java
index b631999c2c54..4e73bd9d3c82 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java
@@ -18,13 +18,19 @@ package android.security.keystore2;
import android.annotation.NonNull;
import android.security.KeyStoreSecurityLevel;
+import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyProperties;
+import android.system.keystore2.Authorization;
import android.system.keystore2.KeyDescriptor;
import android.system.keystore2.KeyMetadata;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
+import java.security.spec.InvalidParameterSpecException;
/**
* {@link ECPublicKey} backed by keystore.
@@ -56,11 +62,45 @@ public class AndroidKeyStoreECPublicKey extends AndroidKeyStorePublicKey impleme
}
}
+ private static String getEcCurveFromKeymaster(int ecCurve) {
+ switch (ecCurve) {
+ case android.hardware.security.keymint.EcCurve.P_224:
+ return "secp224r1";
+ case android.hardware.security.keymint.EcCurve.P_256:
+ return "secp256r1";
+ case android.hardware.security.keymint.EcCurve.P_384:
+ return "secp384r1";
+ case android.hardware.security.keymint.EcCurve.P_521:
+ return "secp521r1";
+ }
+ return "";
+ }
+
+ private ECParameterSpec getCurveSpec(String name)
+ throws NoSuchAlgorithmException, InvalidParameterSpecException {
+ AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
+ parameters.init(new ECGenParameterSpec(name));
+ return parameters.getParameterSpec(ECParameterSpec.class);
+ }
+
@Override
public AndroidKeyStorePrivateKey getPrivateKey() {
+ ECParameterSpec params = mParams;
+ for (Authorization a : getAuthorizations()) {
+ try {
+ if (a.keyParameter.tag == KeymasterDefs.KM_TAG_EC_CURVE) {
+ params = getCurveSpec(getEcCurveFromKeymaster(
+ a.keyParameter.value.getEcCurve()));
+ break;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to parse EC curve "
+ + a.keyParameter.value.getEcCurve());
+ }
+ }
return new AndroidKeyStoreECPrivateKey(
getUserKeyDescriptor(), getKeyIdDescriptor().nspace, getAuthorizations(),
- getSecurityLevel(), mParams);
+ getSecurityLevel(), params);
}
@Override
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
index b1338d164055..4caa47f2078b 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
@@ -31,6 +31,8 @@ import java.security.NoSuchAlgorithmException;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.XECKey;
import java.security.spec.AlgorithmParameterSpec;
import java.util.ArrayList;
import java.util.List;
@@ -132,6 +134,15 @@ public class AndroidKeyStoreKeyAgreementSpi extends KeyAgreementSpi
throw new InvalidKeyException("key == null");
} else if (!(key instanceof PublicKey)) {
throw new InvalidKeyException("Only public keys supported. Key: " + key);
+ } else if (!(mKey instanceof ECKey && key instanceof ECKey)
+ && !(mKey instanceof XECKey && key instanceof XECKey)) {
+ throw new InvalidKeyException(
+ "Public and Private key should be of the same type:");
+ } else if (mKey instanceof ECKey
+ && !((ECKey) key).getParams().getCurve()
+ .equals(((ECKey) mKey).getParams().getCurve())) {
+ throw new InvalidKeyException(
+ "Public and Private key parameters should be same.");
} else if (!lastPhase) {
throw new IllegalStateException(
"Only one other party supported. lastPhase must be set to true.");
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
index 42589640d2b7..e392c8dcca93 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
@@ -22,16 +22,18 @@ import android.system.keystore2.Authorization;
import android.system.keystore2.KeyDescriptor;
import java.security.PrivateKey;
-import java.security.interfaces.EdECKey;
+import java.security.interfaces.XECPrivateKey;
import java.security.spec.NamedParameterSpec;
+import java.util.Optional;
/**
* X25519 Private Key backed by Keystore.
- * instance of {@link PrivateKey} and {@link EdECKey}
+ * instance of {@link PrivateKey} and {@link XECPrivateKey}
*
* @hide
*/
-public class AndroidKeyStoreXDHPrivateKey extends AndroidKeyStorePrivateKey implements EdECKey {
+public class AndroidKeyStoreXDHPrivateKey extends AndroidKeyStorePrivateKey
+ implements XECPrivateKey {
public AndroidKeyStoreXDHPrivateKey(
@NonNull KeyDescriptor descriptor, long keyId,
@NonNull Authorization[] authorizations,
@@ -44,4 +46,12 @@ public class AndroidKeyStoreXDHPrivateKey extends AndroidKeyStorePrivateKey impl
public NamedParameterSpec getParams() {
return NamedParameterSpec.X25519;
}
+
+ @Override
+ public Optional<byte[]> getScalar() {
+ /* An empty Optional if the scalar cannot be extracted (e.g. if the provider is a hardware
+ * token and the private key is not allowed to leave the crypto boundary).
+ */
+ return Optional.empty();
+ }
}
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index a5c0924579eb..b763a96e8e8a 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -169,6 +169,8 @@ void DeferredLayerUpdater::apply() {
sk_sp<SkImage> layerImage = mImageSlots[slot].createIfNeeded(
hardwareBuffer, dataspace, newContent,
mRenderState.getRenderThread().getGrContext());
+ AHardwareBuffer_Desc bufferDesc;
+ AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
// unref to match the ref added by ASurfaceTexture_dequeueBuffer. eglCreateImageKHR
// (invoked by createIfNeeded) will add a ref to the AHardwareBuffer.
AHardwareBuffer_release(hardwareBuffer);
@@ -189,6 +191,7 @@ void DeferredLayerUpdater::apply() {
maxLuminanceNits =
std::max(cta861_3.maxContentLightLevel, maxLuminanceNits);
}
+ mLayer->setBufferFormat(bufferDesc.format);
updateLayer(forceFilter, layerImage, outTransform, currentCropRect,
maxLuminanceNits);
}
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 47eb5d3bfb83..345749b6d920 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -102,6 +102,10 @@ public:
inline float getMaxLuminanceNits() { return mMaxLuminanceNits; }
+ void setBufferFormat(uint32_t format) { mBufferFormat = format; }
+
+ uint32_t getBufferFormat() const { return mBufferFormat; }
+
void draw(SkCanvas* canvas);
protected:
@@ -169,6 +173,8 @@ private:
*/
float mMaxLuminanceNits = -1;
+ uint32_t mBufferFormat = 0;
+
}; // struct Layer
} // namespace uirenderer
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 2fba13c3cfea..3ba540921f64 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -107,6 +107,32 @@ static bool isHdrDataspace(ui::Dataspace dataspace) {
return transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG;
}
+static void adjustCropForYUV(uint32_t format, int bufferWidth, int bufferHeight, SkRect* cropRect) {
+ // Chroma channels of YUV420 images are subsampled we may need to shrink the crop region by
+ // a whole texel on each side. Since skia still adds its own 0.5 inset, we apply an
+ // additional 0.5 inset. See GLConsumer::computeTransformMatrix for details.
+ float shrinkAmount = 0.0f;
+ switch (format) {
+ // Use HAL formats since some AHB formats are only available in vndk
+ case HAL_PIXEL_FORMAT_YCBCR_420_888:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ shrinkAmount = 0.5f;
+ break;
+ default:
+ break;
+ }
+
+ // Shrink the crop if it has more than 1-px and differs from the buffer size.
+ if (cropRect->width() > 1 && cropRect->width() < bufferWidth) {
+ cropRect->inset(shrinkAmount, 0);
+ }
+
+ if (cropRect->height() > 1 && cropRect->height() < bufferHeight) {
+ cropRect->inset(0, shrinkAmount);
+ }
+}
+
// TODO: Context arg probably doesn't belong here – do debug check at callsite instead.
bool LayerDrawable::DrawLayer(GrRecordingContext* context,
SkCanvas* canvas,
@@ -142,6 +168,7 @@ bool LayerDrawable::DrawLayer(GrRecordingContext* context,
SkRect skiaSrcRect;
if (srcRect && !srcRect->isEmpty()) {
skiaSrcRect = *srcRect;
+ adjustCropForYUV(layer->getBufferFormat(), imageWidth, imageHeight, &skiaSrcRect);
} else {
skiaSrcRect = SkRect::MakeIWH(imageWidth, imageHeight);
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 59c914f0198c..03f02de98efe 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -243,7 +243,9 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
mContext->unpinImages();
for (size_t i = 0; i < mLayers.size(); i++) {
- mLayers[i]->apply();
+ if (mLayers[i]) {
+ mLayers[i]->apply();
+ }
}
mLayers.clear();
mContext->setContentDrawBounds(mContentDrawBounds);
diff --git a/libs/incident/Android.bp b/libs/incident/Android.bp
index 547d7192090a..ff1714da2008 100644
--- a/libs/incident/Android.bp
+++ b/libs/incident/Android.bp
@@ -133,4 +133,6 @@ cc_test {
static_libs: [
"libgmock",
],
+
+ host_required: ["compatibility-tradefed"],
}
diff --git a/media/Android.bp b/media/Android.bp
index e97f077b347a..97970dae0fa0 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -90,8 +90,13 @@ aidl_interface {
"aidl/android/media/audio/common/AudioStreamType.aidl",
"aidl/android/media/audio/common/AudioUsage.aidl",
"aidl/android/media/audio/common/AudioUuid.aidl",
+ "aidl/android/media/audio/common/Boolean.aidl",
+ "aidl/android/media/audio/common/Byte.aidl",
"aidl/android/media/audio/common/ExtraAudioDescriptor.aidl",
+ "aidl/android/media/audio/common/Float.aidl",
+ "aidl/android/media/audio/common/Double.aidl",
"aidl/android/media/audio/common/Int.aidl",
+ "aidl/android/media/audio/common/Long.aidl",
"aidl/android/media/audio/common/PcmType.aidl",
],
stability: "vintf",
diff --git a/media/aidl/android/media/audio/common/Boolean.aidl b/media/aidl/android/media/audio/common/Boolean.aidl
new file mode 100644
index 000000000000..fddd5324c534
--- /dev/null
+++ b/media/aidl/android/media/audio/common/Boolean.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audio.common;
+
+/**
+ * This is a simple wrapper around a 'boolean', putting it in a parcelable, so it
+ * can be used as an 'inout' parameter, be made '@nullable', etc.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable Boolean {
+ boolean value;
+}
diff --git a/media/aidl/android/media/audio/common/Byte.aidl b/media/aidl/android/media/audio/common/Byte.aidl
new file mode 100644
index 000000000000..f0a31a2818bf
--- /dev/null
+++ b/media/aidl/android/media/audio/common/Byte.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audio.common;
+
+/**
+ * This is a simple wrapper around a 'byte', putting it in a parcelable, so it
+ * can be used as an 'inout' parameter, be made '@nullable', etc.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable Byte {
+ byte value;
+}
diff --git a/media/aidl/android/media/audio/common/Double.aidl b/media/aidl/android/media/audio/common/Double.aidl
new file mode 100644
index 000000000000..d7ab7b8f6431
--- /dev/null
+++ b/media/aidl/android/media/audio/common/Double.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audio.common;
+
+/**
+ * This is a simple wrapper around a 'double', putting it in a parcelable, so it
+ * can be used as an 'inout' parameter, be made '@nullable', etc.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable Double {
+ double value;
+}
diff --git a/media/aidl/android/media/audio/common/Float.aidl b/media/aidl/android/media/audio/common/Float.aidl
new file mode 100644
index 000000000000..4c5257efa56e
--- /dev/null
+++ b/media/aidl/android/media/audio/common/Float.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audio.common;
+
+/**
+ * This is a simple wrapper around a 'float', putting it in a parcelable, so it
+ * can be used as an 'inout' parameter, be made '@nullable', etc.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable Float {
+ float value;
+}
diff --git a/media/aidl/android/media/audio/common/Long.aidl b/media/aidl/android/media/audio/common/Long.aidl
new file mode 100644
index 000000000000..a4aeb53619c0
--- /dev/null
+++ b/media/aidl/android/media/audio/common/Long.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audio.common;
+
+/**
+ * This is a simple wrapper around a 'long', putting it in a parcelable, so it
+ * can be used as an 'inout' parameter, be made '@nullable', etc.
+ *
+ * {@hide}
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable Long {
+ long value;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Boolean.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Boolean.aidl
new file mode 100644
index 000000000000..bc996e441ba3
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Boolean.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Boolean {
+ boolean value;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Byte.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Byte.aidl
new file mode 100644
index 000000000000..604e74dbf560
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Byte.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Byte {
+ byte value;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Double.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Double.aidl
new file mode 100644
index 000000000000..a525629f2753
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Double.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Double {
+ double value;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Float.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Float.aidl
new file mode 100644
index 000000000000..af98eab83dfd
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Float.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Float {
+ float value;
+}
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Long.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Long.aidl
new file mode 100644
index 000000000000..e403dd3fd4ea
--- /dev/null
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/Long.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.media.audio.common;
+/* @hide */
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable Long {
+ long value;
+}
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index b8e7930e1dca..ad4feecf7d3c 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -335,13 +335,13 @@ final public class MediaMuxer {
}
/**
- * Constructor.
* Creates a media muxer that writes to the specified path.
+ * <p>The caller must not use the file {@code path} before calling {@link #stop}.
* @param path The path of the output media file.
* @param format The format of the output media file.
* @see android.media.MediaMuxer.OutputFormat
* @throws IllegalArgumentException if path is invalid or format is not supported.
- * @throws IOException if failed to open the file for write.
+ * @throws IOException if an error occurs while opening or creating the output file.
*/
public MediaMuxer(@NonNull String path, @Format int format) throws IOException {
if (path == null) {
@@ -363,16 +363,19 @@ final public class MediaMuxer {
}
/**
- * Constructor.
- * Creates a media muxer that writes to the specified FileDescriptor. File descriptor
- * must be seekable and writable. Application should not use the file referenced
- * by this file descriptor until {@link #stop}. It is the application's responsibility
- * to close the file descriptor. It is safe to do so as soon as this call returns.
- * @param fd The FileDescriptor of the output media file.
+ * Creates a media muxer that writes to the specified FileDescriptor.
+ * <p>The caller must not use the file referenced by the specified {@code fd} before calling
+ * {@link #stop}.
+ * <p>It is the caller's responsibility to close the file descriptor, which is safe to do so
+ * as soon as this call returns.
+ * @param fd The FileDescriptor of the output media file. If {@code format} is
+ * {@link OutputFormat#MUXER_OUTPUT_WEBM}, {@code fd} must be open in read-write mode.
+ * Otherwise, write mode is sufficient, but read-write is also accepted.
* @param format The format of the output media file.
* @see android.media.MediaMuxer.OutputFormat
- * @throws IllegalArgumentException if fd is invalid or format is not supported.
- * @throws IOException if failed to open the file for write.
+ * @throws IllegalArgumentException if {@code format} is not supported, or if {@code fd} is
+ * not open in the expected mode.
+ * @throws IOException if an error occurs while performing an IO operation.
*/
public MediaMuxer(@NonNull FileDescriptor fd, @Format int format) throws IOException {
setUpMediaMuxer(fd, format);
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index 267917653efb..b664325ab0d1 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -165,7 +165,11 @@ static jlong android_media_MediaMuxer_native_setup(
MediaMuxer::OutputFormat fileFormat =
static_cast<MediaMuxer::OutputFormat>(format);
- sp<MediaMuxer> muxer = new MediaMuxer(fd, fileFormat);
+ sp<MediaMuxer> muxer = MediaMuxer::create(fd, fileFormat);
+ if (muxer == nullptr) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Muxer creation failed");
+ return 0;
+ }
muxer->incStrong(clazz);
return reinterpret_cast<jlong>(muxer.get());
}
diff --git a/media/native/midi/Android.bp b/media/native/midi/Android.bp
index 7acb8c744ba7..a991a71fd3f1 100644
--- a/media/native/midi/Android.bp
+++ b/media/native/midi/Android.bp
@@ -74,4 +74,8 @@ ndk_library {
symbol_file: "libamidi.map.txt",
first_version: "29",
+ export_header_libs: [
+ "amidi",
+ ],
+
}
diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h
index fbb7fb329659..2b3170326285 100644
--- a/media/native/midi/include/amidi/AMidi.h
+++ b/media/native/midi/include/amidi/AMidi.h
@@ -66,7 +66,7 @@ enum {
*
* Introduced in API 33.
*/
-enum AMidiDevice_Protocol : int32_t {
+typedef enum AMidiDevice_Protocol : int32_t {
/**
* Constant representing a default protocol with Universal MIDI Packets (UMP).
* UMP is defined in "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" spec.
@@ -131,7 +131,7 @@ enum AMidiDevice_Protocol : int32_t {
* MIDI-CI is defined in "MIDI Capability Inquiry (MIDI-CI)" spec.
*/
AMIDI_DEVICE_PROTOCOL_UNKNOWN = -1
-};
+} AMidiDevice_Protocol;
/*
* Device API
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 32b7a0780e63..8594ba5ca2da 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -27,6 +27,9 @@ ndk_library {
symbol_file: "libandroid.map.txt",
first_version: "9",
unversioned_until: "current",
+ export_header_libs: [
+ "libandroid_headers",
+ ],
}
cc_defaults {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
index fe337d267f25..8e33ca338eb1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
@@ -106,13 +106,20 @@ public class LicenseHtmlGeneratorFromXmlTest {
+ "license content #1\n"
+ "</pre><!-- license-text -->\n"
+ "</td></tr><!-- same-license -->\n"
- + "</table></body></html>\n";
+ + "</table>\n"
+ + "<div class=\"path-counts\"><table>\n"
+ + " <tr><th>Path prefix</th><th>Count</th></tr>\n\n"
+ + " <tr><td>file0</td><td>1</td></tr>\n"
+ + " <tr><td>file1</td><td>1</td></tr>\n"
+ + "</table></div>\n\n"
+ + "</body></html>\n";
private static final String HTML_NEW_BODY_STRING =
"<strong>Libraries</strong>\n"
+ "<ul class=\"libraries\">\n"
+ "<li><a href=\"#id0\">libA</a></li>\n"
+ "<li><a href=\"#id1\">libB</a></li>\n"
+ + "<li><a href=\"#id0\">libC</a></li>\n"
+ "</ul>\n"
+ "<strong>Files</strong>\n"
+ "<ul class=\"files\">\n"
@@ -146,7 +153,14 @@ public class LicenseHtmlGeneratorFromXmlTest {
+ "license content #1\n"
+ "</pre><!-- license-text -->\n"
+ "</td></tr><!-- same-license -->\n"
- + "</table></body></html>\n";
+ + "</table>\n"
+ + "<div class=\"path-counts\"><table>\n"
+ + " <tr><th>Path prefix</th><th>Count</th></tr>\n\n"
+ + " <tr><td>file0</td><td>1</td></tr>\n"
+ + " <tr><td>file1</td><td>1</td></tr>\n"
+ + " <tr><td>file2</td><td>1</td></tr>\n"
+ + "</table></div>\n\n"
+ + "</body></html>\n";
private static final String EXPECTED_OLD_HTML_STRING = HTML_HEAD_STRING + HTML_OLD_BODY_STRING;
@@ -263,7 +277,7 @@ public class LicenseHtmlGeneratorFromXmlTest {
Map<String, Set<String>> toOne = new HashMap<>();
toBoth.put("", new HashSet<String>(Arrays.asList("0", "1")));
- toOne.put("", new HashSet<String>(Arrays.asList("0", "1")));
+ toOne.put("", new HashSet<String>(Arrays.asList("0")));
fileNameToLibraryToContentIdMap.put("/file0", toBoth);
fileNameToLibraryToContentIdMap.put("/file1", toOne);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index b971f7a70ca9..979e9eaa1e84 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -680,6 +680,9 @@
<!-- Permission required for CTS test - Notification test suite -->
<uses-permission android:name="android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL" />
+ <!-- Permission required for test - CellBroadcastComplianceTest -->
+ <uses-permission android:name="com.android.cellbroadcastservice.FULL_ACCESS_CELL_BROADCAST_HISTORY" />
+
<!-- Permission required for CTS test - CaptioningManagerTest -->
<uses-permission android:name="android.permission.SET_SYSTEM_AUDIO_CAPTION" />
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 104998c53e09..0333b2d779df 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -228,7 +228,7 @@ android_library {
"metrics-helper-lib",
"hamcrest-library",
"androidx.test.rules",
- "androidx.test.uiautomator",
+ "androidx.test.uiautomator_uiautomator",
"mockito-target-extended-minus-junit4",
"testables",
"truth-prebuilt",
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index b8a00133c728..1f7021e514e5 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -18,6 +18,7 @@ package com.android.systemui.controls.ui
import android.annotation.AnyThread
import android.annotation.MainThread
+import android.app.Activity
import android.app.AlertDialog
import android.app.Dialog
import android.app.PendingIntent
@@ -119,8 +120,16 @@ class ControlActionCoordinatorImpl @Inject constructor(
}
override fun closeDialogs() {
- dialog?.dismiss()
- dialog = null
+ val isActivityFinishing =
+ (activityContext as? Activity)?.let { it.isFinishing || it.isDestroyed }
+ if (isActivityFinishing == true) {
+ dialog = null
+ return
+ }
+ if (dialog?.isShowing == true) {
+ dialog?.dismiss()
+ dialog = null
+ }
}
override fun toggle(cvh: ControlViewHolder, templateId: String, isChecked: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 33453a4c31d6..159784575b69 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -631,9 +631,22 @@ public class MediaControlPanel {
Drawable artwork;
boolean isArtworkBound;
Icon artworkIcon = data.getArtwork();
+ WallpaperColors wallpaperColors = null;
if (artworkIcon != null) {
- WallpaperColors wallpaperColors = WallpaperColors
- .fromBitmap(artworkIcon.getBitmap());
+ if (artworkIcon.getType() == Icon.TYPE_BITMAP
+ || artworkIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
+ // Avoids extra processing if this is already a valid bitmap
+ wallpaperColors = WallpaperColors
+ .fromBitmap(artworkIcon.getBitmap());
+ } else {
+ Drawable artworkDrawable = artworkIcon.loadDrawable(mContext);
+ if (artworkDrawable != null) {
+ wallpaperColors = WallpaperColors
+ .fromDrawable(artworkIcon.loadDrawable(mContext));
+ }
+ }
+ }
+ if (wallpaperColors != null) {
mutableColorScheme = new ColorScheme(wallpaperColors, true, Style.CONTENT);
artwork = getScaledBackground(artworkIcon, width, height);
isArtworkBound = true;
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index f2f275323d58..1ab0b5e263d1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -269,6 +269,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
}
private void onGroupActionTriggered(boolean isChecked, MediaDevice device) {
+ disableSeekBar();
if (isChecked && isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
mController.addDeviceToPlayMedia(device);
} else if (!isChecked && isDeviceIncluded(mController.getDeselectableMediaDevice(),
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index bec67397a926..3b4ca48046eb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -273,6 +273,8 @@ public abstract class MediaOutputBaseAdapter extends
void initSeekbar(MediaDevice device, boolean isCurrentSeekbarInvisible) {
if (!mController.isVolumeControlEnabled(device)) {
disableSeekBar();
+ } else {
+ enableSeekBar();
}
mSeekBar.setMaxVolume(device.getMaxVolume());
final int currentVolume = device.getCurrentVolume();
@@ -417,11 +419,16 @@ public abstract class MediaOutputBaseAdapter extends
return drawable;
}
- private void disableSeekBar() {
+ protected void disableSeekBar() {
mSeekBar.setEnabled(false);
mSeekBar.setOnTouchListener((v, event) -> true);
}
+ private void enableSeekBar() {
+ mSeekBar.setEnabled(true);
+ mSeekBar.setOnTouchListener((v, event) -> false);
+ }
+
protected void setUpDeviceIcon(MediaDevice device) {
ThreadUtils.postOnBackgroundThread(() -> {
Icon icon = mController.getDeviceIconCompat(device).toIcon(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java
index 5d7af522176a..6fe06e085556 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java
@@ -194,6 +194,11 @@ public class MediaOutputMetricLogger {
}
private int getLoggingDeviceType(MediaDevice device, boolean isSourceDevice) {
+ if (device == null) {
+ return isSourceDevice
+ ? SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__SOURCE__UNKNOWN_TYPE
+ : SysUiStatsLog.MEDIA_OUTPUT_OP_SWITCH_REPORTED__TARGET__UNKNOWN_TYPE;
+ }
switch (device.getDeviceType()) {
case MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE:
return isSourceDevice
@@ -229,6 +234,9 @@ public class MediaOutputMetricLogger {
}
private int getInteractionDeviceType(MediaDevice device) {
+ if (device == null) {
+ return SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__TARGET__UNKNOWN_TYPE;
+ }
switch (device.getDeviceType()) {
case MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE:
return SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__TARGET__BUILTIN_SPEAKER;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index fbdabc74aba4..fcd9e10089bc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -19,8 +19,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings.Secure;
@@ -28,6 +26,7 @@ import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import com.android.internal.logging.InstanceId;
@@ -35,9 +34,7 @@ import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.PluginListener;
@@ -68,12 +65,20 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.Executor;
import java.util.function.Predicate;
import javax.inject.Inject;
import javax.inject.Provider;
-/** Platform implementation of the quick settings tile host **/
+/** Platform implementation of the quick settings tile host
+ *
+ * This class keeps track of the set of current tiles and is the in memory source of truth
+ * (ground truth is kept in {@link Secure#QS_TILES}). When the ground truth changes,
+ * {@link #onTuningChanged} will be called and the tiles will be re-created as needed.
+ *
+ * This class also provides the interface for adding/removing/changing tiles.
+ */
@SysUISingleton
public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, Dumpable {
private static final String TAG = "QSTileHost";
@@ -89,11 +94,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
private final TunerService mTunerService;
private final PluginManager mPluginManager;
private final DumpManager mDumpManager;
- private final BroadcastDispatcher mBroadcastDispatcher;
private final QSLogger mQSLogger;
private final UiEventLogger mUiEventLogger;
private final InstanceIdSequence mInstanceIdSequence;
private final CustomTileStatePersister mCustomTileStatePersister;
+ private final Executor mMainExecutor;
private final List<Callback> mCallbacks = new ArrayList<>();
@Nullable
@@ -113,13 +118,11 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
public QSTileHost(Context context,
StatusBarIconController iconController,
QSFactory defaultFactory,
- @Main Handler mainHandler,
- @Background Looper bgLooper,
+ @Main Executor mainExecutor,
PluginManager pluginManager,
TunerService tunerService,
Provider<AutoTileManager> autoTiles,
DumpManager dumpManager,
- BroadcastDispatcher broadcastDispatcher,
Optional<CentralSurfaces> centralSurfacesOptional,
QSLogger qsLogger,
UiEventLogger uiEventLogger,
@@ -137,7 +140,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
mDumpManager = dumpManager;
mQSLogger = qsLogger;
mUiEventLogger = uiEventLogger;
- mBroadcastDispatcher = broadcastDispatcher;
+ mMainExecutor = mainExecutor;
mTileServiceRequestController = tileServiceRequestControllerBuilder.create(this);
mTileLifeCycleManagerFactory = tileLifecycleManagerFactory;
@@ -151,7 +154,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
mSecureSettings = secureSettings;
mCustomTileStatePersister = customTileStatePersister;
- mainHandler.post(() -> {
+ mainExecutor.execute(() -> {
// This is technically a hack to avoid circular dependency of
// QSTileHost -> XXXTile -> QSTileHost. Posting ensures creation
// finishes before creating any tiles.
@@ -258,6 +261,33 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
return mTileSpecs.indexOf(spec);
}
+ /**
+ * Whenever the Secure Setting keeping track of the current tiles changes (or upon start) this
+ * will be called with the new value of the setting.
+ *
+ * This method will do the following:
+ * <ol>
+ * <li>Destroy any existing tile that's not one of the current tiles (in the setting)</li>
+ * <li>Create new tiles for those that don't already exist. If this tiles end up being
+ * not available, they'll also be destroyed.</li>
+ * <li>Save the resolved list of tiles (current tiles that are available) into the setting.
+ * This means that after this call ends, the tiles in the Setting, {@link #mTileSpecs},
+ * and visible tiles ({@link #mTiles}) must match.
+ * </li>
+ * </ol>
+ *
+ * Additionally, if the user has changed, it'll do the following:
+ * <ul>
+ * <li>Change the user for SystemUI tiles: {@link QSTile#userSwitch}.</li>
+ * <li>Destroy any {@link CustomTile} and recreate it for the new user.</li>
+ * </ul>
+ *
+ * This happens in main thread as {@link com.android.systemui.tuner.TunerServiceImpl} dispatches
+ * in main thread.
+ *
+ * @see QSTile#isAvailable
+ */
+ @MainThread
@Override
public void onTuningChanged(String key, String newValue) {
if (!TILES_SETTING.equals(key)) {
@@ -330,34 +360,44 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
mCurrentUser = currentUser;
List<String> currentSpecs = new ArrayList<>(mTileSpecs);
mTileSpecs.clear();
- mTileSpecs.addAll(tileSpecs);
+ mTileSpecs.addAll(newTiles.keySet()); // Only add the valid (available) tiles.
mTiles.clear();
mTiles.putAll(newTiles);
if (newTiles.isEmpty() && !tileSpecs.isEmpty()) {
// If we didn't manage to create any tiles, set it to empty (default)
Log.d(TAG, "No valid tiles on tuning changed. Setting to default.");
- changeTiles(currentSpecs, loadTileSpecs(mContext, ""));
+ changeTilesByUser(currentSpecs, loadTileSpecs(mContext, ""));
} else {
+ String resolvedTiles = TextUtils.join(",", mTileSpecs);
+ if (!resolvedTiles.equals(newValue)) {
+ // If the resolved tiles (those we actually ended up with) are different than
+ // the ones that are in the setting, update the Setting.
+ saveTilesToSettings(mTileSpecs);
+ }
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).onTilesChanged();
}
}
}
+ /**
+ * Only use with [CustomTile] if the tile doesn't exist anymore (and therefore doesn't need
+ * its lifecycle terminated).
+ */
@Override
public void removeTile(String spec) {
- changeTileSpecs(tileSpecs-> tileSpecs.remove(spec));
+ mMainExecutor.execute(() -> changeTileSpecs(tileSpecs-> tileSpecs.remove(spec)));
}
/**
* Remove many tiles at once.
*
- * It will only save to settings once (as opposed to {@link QSTileHost#removeTile} called
+ * It will only save to settings once (as opposed to {@link QSTileHost#removeTileByUser} called
* multiple times).
*/
@Override
public void removeTiles(Collection<String> specs) {
- changeTileSpecs(tileSpecs -> tileSpecs.removeAll(specs));
+ mMainExecutor.execute(() -> changeTileSpecs(tileSpecs -> tileSpecs.removeAll(specs)));
}
@Override
@@ -381,27 +421,30 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
* @param requestPosition -1 for end, 0 for beginning, or X for insertion at position X
*/
public void addTile(String spec, int requestPosition) {
- if (spec.equals("work")) Log.wtfStack(TAG, "Adding work tile");
- changeTileSpecs(tileSpecs -> {
- if (tileSpecs.contains(spec)) return false;
-
- int size = tileSpecs.size();
- if (requestPosition == POSITION_AT_END || requestPosition >= size) {
- tileSpecs.add(spec);
- } else {
- tileSpecs.add(requestPosition, spec);
- }
- return true;
- });
+ mMainExecutor.execute(() ->
+ changeTileSpecs(tileSpecs -> {
+ if (tileSpecs.contains(spec)) return false;
+
+ int size = tileSpecs.size();
+ if (requestPosition == POSITION_AT_END || requestPosition >= size) {
+ tileSpecs.add(spec);
+ } else {
+ tileSpecs.add(requestPosition, spec);
+ }
+ return true;
+ })
+ );
}
- void saveTilesToSettings(List<String> tileSpecs) {
- if (tileSpecs.contains("work")) Log.wtfStack(TAG, "Saving work tile");
+
+ @MainThread
+ private void saveTilesToSettings(List<String> tileSpecs) {
mSecureSettings.putStringForUser(TILES_SETTING, TextUtils.join(",", tileSpecs),
null /* tag */, false /* default */, mCurrentUser,
true /* overrideable by restore */);
}
+ @MainThread
private void changeTileSpecs(Predicate<List<String>> changeFunction) {
final String setting = mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser);
final List<String> tileSpecs = loadTileSpecs(mContext, setting);
@@ -421,29 +464,32 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
*/
public void addTile(ComponentName tile, boolean end) {
String spec = CustomTile.toSpec(tile);
- if (!mTileSpecs.contains(spec)) {
- List<String> newSpecs = new ArrayList<>(mTileSpecs);
- if (end) {
- newSpecs.add(spec);
- } else {
- newSpecs.add(0, spec);
- }
- changeTiles(mTileSpecs, newSpecs);
- }
+ addTile(spec, end ? POSITION_AT_END : 0);
}
- public void removeTile(ComponentName tile) {
- List<String> newSpecs = new ArrayList<>(mTileSpecs);
- newSpecs.remove(CustomTile.toSpec(tile));
- changeTiles(mTileSpecs, newSpecs);
+ /**
+ * This will call through {@link #changeTilesByUser}. It should only be used when a tile is
+ * removed by a <b>user action</b> like {@code adb}.
+ */
+ public void removeTileByUser(ComponentName tile) {
+ mMainExecutor.execute(() -> {
+ List<String> newSpecs = new ArrayList<>(mTileSpecs);
+ if (newSpecs.remove(CustomTile.toSpec(tile))) {
+ changeTilesByUser(mTileSpecs, newSpecs);
+ }
+ });
}
/**
* Change the tiles triggered by the user editing.
* <p>
* This is not called on device start, or on user change.
+ *
+ * {@link android.service.quicksettings.TileService#onTileRemoved} will be called for tiles
+ * that are removed.
*/
- public void changeTiles(List<String> previousTiles, List<String> newTiles) {
+ @MainThread
+ public void changeTilesByUser(List<String> previousTiles, List<String> newTiles) {
final List<String> copy = new ArrayList<>(previousTiles);
final int NP = copy.size();
for (int i = 0; i < NP; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index e52bfbd67275..d84b12c714bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -182,7 +182,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
for (int i = 1; i < mTiles.size() && mTiles.get(i) != null; i++) {
newSpecs.add(mTiles.get(i).spec);
}
- host.changeTiles(mCurrentSpecs, newSpecs);
+ host.changeTilesByUser(mCurrentSpecs, newSpecs);
mCurrentSpecs = newSpecs;
}
@@ -200,7 +200,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
/** */
public void resetTileSpecs(List<String> specs) {
// Notify the host so the tiles get removed callbacks.
- mHost.changeTiles(mCurrentSpecs, specs);
+ mHost.changeTilesByUser(mCurrentSpecs, specs);
setTileSpecs(specs);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index bf565a8c52e0..cfc57db2eeb8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -289,7 +289,7 @@ public class TileServiceManager {
}
}
- mServices.getHost().removeTile(component);
+ mServices.getHost().removeTile(CustomTile.toSpec(component));
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 38a208b72edc..f4ca7edb146d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -642,6 +642,8 @@ public class NotificationLockscreenUserManagerImpl implements
// - device keyguard is shown in secure mode;
// - profile is locked with a work challenge.
SparseArray<UserInfo> currentProfiles = getCurrentProfiles();
+ SparseBooleanArray oldPublicModes = mLockscreenPublicMode.clone();
+ SparseBooleanArray oldWorkChallenges = mUsersWithSeparateWorkChallenge.clone();
mUsersWithSeparateWorkChallenge.clear();
for (int i = currentProfiles.size() - 1; i >= 0; i--) {
final int userId = currentProfiles.valueAt(i).id;
@@ -660,7 +662,10 @@ public class NotificationLockscreenUserManagerImpl implements
}
getEntryManager().updateNotifications("NotificationLockscreenUserManager.updatePublicMode");
// TODO(b/234738798): Migrate KeyguardNotificationVisibilityProvider to use this listener
- // notifyNotificationStateChanged();
+ if (!mLockscreenPublicMode.equals(oldPublicModes)
+ || !mUsersWithSeparateWorkChallenge.equals(oldWorkChallenges)) {
+ notifyNotificationStateChanged();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
index 6c99e3adb73e..bef3d5095cb7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
@@ -20,8 +20,10 @@ import android.service.notification.StatusBarNotification
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.log.dagger.NotificationHeadsUpLog
import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
import javax.inject.Inject
class NotificationInterruptLogger @Inject constructor(
@@ -212,6 +214,33 @@ class NotificationInterruptLogger @Inject constructor(
})
}
+ fun logNoFullscreen(entry: NotificationEntry, reason: String) {
+ hunBuffer.log(TAG, DEBUG, {
+ str1 = entry.key
+ str2 = reason
+ }, {
+ "No FullScreenIntent: $str2: $str1"
+ })
+ }
+
+ fun logNoFullscreenWarning(entry: NotificationEntry, reason: String) {
+ hunBuffer.log(TAG, WARNING, {
+ str1 = entry.key
+ str2 = reason
+ }, {
+ "No FullScreenIntent: WARNING: $str2: $str1"
+ })
+ }
+
+ fun logFullscreen(entry: NotificationEntry, reason: String) {
+ hunBuffer.log(TAG, DEBUG, {
+ str1 = entry.key
+ str2 = reason
+ }, {
+ "FullScreenIntent: $str2: $str1"
+ })
+ }
+
fun keyguardHideNotification(key: String) {
hunBuffer.log(TAG, DEBUG, {
str1 = key
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index e210f193b0a1..e1ddbd23e51a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -177,9 +177,69 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
*/
@Override
public boolean shouldLaunchFullScreenIntentWhenAdded(NotificationEntry entry) {
- return entry.getSbn().getNotification().fullScreenIntent != null
- && (!shouldHeadsUp(entry)
- || mStatusBarStateController.getState() == StatusBarState.KEYGUARD);
+ if (entry.getSbn().getNotification().fullScreenIntent == null) {
+ return false;
+ }
+
+ // Never show FSI when suppressed by DND
+ if (entry.shouldSuppressFullScreenIntent()) {
+ mLogger.logNoFullscreen(entry, "Suppressed by DND");
+ return false;
+ }
+
+ // Never show FSI if importance is not HIGH
+ if (entry.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
+ mLogger.logNoFullscreen(entry, "Not important enough");
+ return false;
+ }
+
+ // If the notification has suppressive GroupAlertBehavior, block FSI and warn.
+ StatusBarNotification sbn = entry.getSbn();
+ if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
+ // b/231322873: Detect and report an event when a notification has both an FSI and a
+ // suppressive groupAlertBehavior, and now correctly block the FSI from firing.
+ final int uid = entry.getSbn().getUid();
+ android.util.EventLog.writeEvent(0x534e4554, "231322873", uid, "groupAlertBehavior");
+ mLogger.logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
+ return false;
+ }
+
+ // If the screen is off, then launch the FullScreenIntent
+ if (!mPowerManager.isInteractive()) {
+ mLogger.logFullscreen(entry, "Device is not interactive");
+ return true;
+ }
+
+ // If the device is currently dreaming, then launch the FullScreenIntent
+ if (isDreaming()) {
+ mLogger.logFullscreen(entry, "Device is dreaming");
+ return true;
+ }
+
+ // If the keyguard is showing, then launch the FullScreenIntent
+ if (mStatusBarStateController.getState() == StatusBarState.KEYGUARD) {
+ mLogger.logFullscreen(entry, "Keyguard is showing");
+ return true;
+ }
+
+ // If the notification should HUN, then we don't need FSI
+ if (shouldHeadsUp(entry)) {
+ mLogger.logNoFullscreen(entry, "Expected to HUN");
+ return false;
+ }
+
+ // If the notification won't HUN for some other reason (DND/snooze/etc), launch FSI.
+ mLogger.logFullscreen(entry, "Expected not to HUN");
+ return true;
+ }
+
+ private boolean isDreaming() {
+ try {
+ return mDreamManager.isDreaming();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to query dream manager.", e);
+ return false;
+ }
}
private boolean shouldHeadsUpWhenAwake(NotificationEntry entry) {
@@ -219,13 +279,7 @@ public class NotificationInterruptStateProviderImpl implements NotificationInter
return false;
}
- boolean isDreaming = false;
- try {
- isDreaming = mDreamManager.isDreaming();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to query dream manager.", e);
- }
- boolean inUse = mPowerManager.isScreenOn() && !isDreaming;
+ boolean inUse = mPowerManager.isScreenOn() && !isDreaming();
if (!inUse) {
mLogger.logNoHeadsUpNotInUse(sbn);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 010e6cf90817..e5f8424a2a24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -339,6 +339,13 @@ public class NotificationStackScrollLayoutController {
};
/**
+ * Recalculate sensitiveness without animation; called when waking up while keyguard occluded.
+ */
+ public void updateSensitivenessForOccludedWakeup() {
+ mView.updateSensitiveness(false, mLockscreenUserManager.isAnyProfilePublicMode());
+ }
+
+ /**
* Set the overexpansion of the panel to be applied to the view.
*/
public void setOverExpansion(float overExpansion) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 8782be50794f..9070eadd9944 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -428,7 +428,7 @@ public class AutoTileManager implements UserAwareController {
if (isSafetyCenterEnabled && !mAutoTracker.isAdded(mSafetySpec)) {
initSafetyTile();
} else if (!isSafetyCenterEnabled && mAutoTracker.isAdded(mSafetySpec)) {
- mHost.removeTile(CustomTile.getComponentFromSpec(mSafetySpec));
+ mHost.removeTile(mSafetySpec);
mHost.unmarkTileAsAutoAdded(mSafetySpec);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 9060d5f67913..ffd50ab5af37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -187,7 +187,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
public void remQsTile(ComponentName tile) {
QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController();
if (qsPanelController != null && qsPanelController.getHost() != null) {
- qsPanelController.getHost().removeTile(tile);
+ qsPanelController.getHost().removeTileByUser(tile);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 7e57dd452cb8..e9a837bc84e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -3384,7 +3384,8 @@ public class CentralSurfacesImpl extends CoreStartable implements
// lock screen where users can use the UDFPS affordance to enter the device
mStatusBarKeyguardViewManager.reset(true);
} else if ((mState == StatusBarState.KEYGUARD
- && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing())
+ && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()
+ && isKeyguardSecure())
|| mState == StatusBarState.SHADE_LOCKED) {
mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */);
}
@@ -3687,6 +3688,18 @@ public class CentralSurfacesImpl extends CoreStartable implements
public void onFinishedWakingUp() {
mWakeUpCoordinator.setFullyAwake(true);
mWakeUpCoordinator.setWakingUp(false);
+ if (mKeyguardStateController.isOccluded()
+ && !mDozeParameters.canControlUnlockedScreenOff()) {
+ // When the keyguard is occluded we don't use the KEYGUARD state which would
+ // normally cause these redaction updates. If AOD is on, the KEYGUARD state is used
+ // to show the doze, AND UnlockedScreenOffAnimationController.onFinishedWakingUp()
+ // would force a KEYGUARD state that would take care of recalculating redaction.
+ // So if AOD is off or unsupported we need to trigger these updates at screen on
+ // when the keyguard is occluded.
+ mLockscreenUserManager.updatePublicMode();
+ mNotificationPanelViewController.getNotificationStackScrollLayoutController()
+ .updateSensitivenessForOccludedWakeup();
+ }
if (mLaunchCameraWhenFinishedWaking) {
mNotificationPanelViewController.launchCamera(
false /* animate */, mLastCameraLaunchSource);
diff --git a/packages/SystemUI/tests/Android.bp b/packages/SystemUI/tests/Android.bp
new file mode 100644
index 000000000000..3c418ed49adc
--- /dev/null
+++ b/packages/SystemUI/tests/Android.bp
@@ -0,0 +1,50 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+android_test {
+ name: "SystemUITests",
+
+ dxflags: ["--multi-dex"],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ static_libs: ["SystemUI-tests"],
+ compile_multilib: "both",
+
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libmultiplejvmtiagentsinterferenceagent",
+ "libstaticjvmtiagent",
+ ],
+ libs: [
+ "android.test.runner",
+ "telephony-common",
+ "android.test.base",
+ ],
+ aaptflags: [
+ "--extra-packages com.android.systemui",
+ ],
+
+ // sign this with platform cert, so this test is allowed to inject key events into
+ // UI it doesn't own. This is necessary to allow screenshots to be taken
+ certificate: "platform",
+
+ additional_manifests: ["AndroidManifest.xml"],
+ manifest: "AndroidManifest-base.xml",
+}
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
deleted file mode 100644
index ff5165d4e7cf..000000000000
--- a/packages/SystemUI/tests/Android.mk
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JACK_FLAGS := --multi-dex native
-LOCAL_DX_FLAGS := --multi-dex
-
-LOCAL_PACKAGE_NAME := SystemUITests
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- SystemUI-tests
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
- libdexmakerjvmtiagent \
- libmultiplejvmtiagentsinterferenceagent \
- libstaticjvmtiagent
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner \
- telephony-common \
- android.test.base \
-
-LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui
-
-# sign this with platform cert, so this test is allowed to inject key events into
-# UI it doesn't own. This is necessary to allow screenshots to be taken
-LOCAL_CERTIFICATE := platform
-
-LOCAL_FULL_LIBS_MANIFEST_FILES := $(LOCAL_PATH)/AndroidManifest.xml
-LOCAL_MANIFEST_FILE := AndroidManifest-base.xml
-
-# Provide jack a list of classes to exclude from code coverage.
-# This is needed because the SystemUITests compile SystemUI source directly, rather than using
-# LOCAL_INSTRUMENTATION_FOR := SystemUI.
-#
-# We want to exclude the test classes from code coverage measurements, but they share the same
-# package as the rest of SystemUI so they can't be easily filtered by package name.
-#
-# Generate a comma separated list of patterns based on the test source files under src/
-# SystemUI classes are in ../src/ so they won't be excluded.
-# Example:
-# Input files: src/com/android/systemui/Test.java src/com/android/systemui/AnotherTest.java
-# Generated exclude list: com.android.systemui.Test*,com.android.systemui.AnotherTest*
-
-# Filter all src files under src/ to just java files
-local_java_files := $(filter %.java,$(call all-java-files-under, src))
-# Transform java file names into full class names.
-# This only works if the class name matches the file name and the directory structure
-# matches the package.
-local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
-local_comma := ,
-local_empty :=
-local_space := $(local_empty) $(local_empty)
-# Convert class name list to jacoco exclude list
-# This appends a * to all classes and replace the space separators with commas.
-jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
-
-LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.systemui.*,com.android.keyguard.*
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
-
-ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
- include $(BUILD_PACKAGE)
-endif
-
-# Reset variables
-local_java_files :=
-local_classes :=
-local_comma :=
-local_space :=
-jacoco_exclude :=
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 241ed2443e6c..6f4579bb14b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -547,6 +547,19 @@ public class MediaControlPanelTest : SysuiTestCase() {
}
@Test
+ fun bindAlbumView_artUsesResource() {
+ val albumArt = Icon.createWithResource(context, R.drawable.ic_android)
+ val state = mediaData.copy(artwork = albumArt)
+
+ player.attachPlayer(viewHolder)
+ player.bindPlayer(state, PACKAGE)
+ bgExecutor.runAllReady()
+ mainExecutor.runAllReady()
+
+ verify(albumView).setImageDrawable(any(Drawable::class.java))
+ }
+
+ @Test
fun bindAlbumView_setAfterExecutors() {
val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bmp)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 59475cf0cb90..c4cb8339c4d6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -274,4 +274,30 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
verify(mMediaOutputController).connectDevice(mMediaDevice2);
}
+
+ @Test
+ public void onItemClick_onGroupActionTriggered_verifySeekbarDisabled() {
+ when(mMediaOutputController.getSelectedMediaDevice()).thenReturn(mMediaDevices);
+ List<MediaDevice> selectableDevices = new ArrayList<>();
+ selectableDevices.add(mMediaDevice1);
+ when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(selectableDevices);
+ when(mMediaOutputController.hasAdjustVolumeUserRestriction()).thenReturn(true);
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ mViewHolder.mContainerLayout.performClick();
+
+ assertThat(mViewHolder.mSeekBar.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void onBindViewHolder_volumeControlChangeToEnabled_enableSeekbarAgain() {
+ when(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(false);
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+ assertThat(mViewHolder.mSeekBar.isEnabled()).isFalse();
+
+ when(mMediaOutputController.isVolumeControlEnabled(mMediaDevice1)).thenReturn(true);
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.mSeekBar.isEnabled()).isTrue();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 664af75a6529..32c66d25d4aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -32,8 +32,6 @@ import android.app.Fragment;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.LayoutInflater;
@@ -42,36 +40,23 @@ import android.view.ViewGroup;
import androidx.test.filters.SmallTest;
-import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.BouncerPanelExpansionCalculator;
import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.animation.ShadeInterpolation;
-import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
-import com.android.systemui.qs.external.CustomTileStatePersister;
-import com.android.systemui.qs.external.TileLifecycleManager;
import com.android.systemui.qs.external.TileServiceRequestController;
-import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.tileimpl.QSFactoryImpl;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.phone.AutoTileManager;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.animation.UniqueObjectHostView;
-import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -79,8 +64,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.util.Optional;
-
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
@@ -125,34 +108,11 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mFragments.dispatchResume();
processAllMessages();
- QSTileHost host =
- new QSTileHost(
- mContext,
- mock(StatusBarIconController.class),
- mock(QSFactoryImpl.class),
- new Handler(),
- Looper.myLooper(),
- mock(PluginManager.class),
- mock(TunerService.class),
- () -> mock(AutoTileManager.class),
- mock(DumpManager.class),
- mock(BroadcastDispatcher.class),
- Optional.of(mock(CentralSurfaces.class)),
- mock(QSLogger.class),
- mock(UiEventLogger.class),
- mock(UserTracker.class),
- mock(SecureSettings.class),
- mock(CustomTileStatePersister.class),
- mTileServiceRequestControllerBuilder,
- mock(TileLifecycleManager.Factory.class));
-
qs.setListening(true);
processAllMessages();
qs.setListening(false);
processAllMessages();
- host.destroy();
- processAllMessages();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 8cf3fe274848..7dbc561fbfc1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -32,12 +32,11 @@ import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.database.ContentObserver;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
import androidx.annotation.Nullable;
@@ -48,7 +47,6 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.CollectionUtils;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.ActivityStarter;
@@ -68,8 +66,10 @@ import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -81,18 +81,19 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Provider;
@RunWith(AndroidTestingRunner.class)
@SmallTest
-@RunWithLooper(setAsMainLooper = true)
public class QSTileHostTest extends SysuiTestCase {
private static String MOCK_STATE_STRING = "MockState";
private static ComponentName CUSTOM_TILE =
ComponentName.unflattenFromString("TEST_PKG/.TEST_CLS");
private static final String CUSTOM_TILE_SPEC = CustomTile.toSpec(CUSTOM_TILE);
+ private static final String SETTING = QSTileHost.TILES_SETTING;
@Mock
private StatusBarIconController mIconController;
@@ -107,8 +108,6 @@ public class QSTileHostTest extends SysuiTestCase {
@Mock
private DumpManager mDumpManager;
@Mock
- private BroadcastDispatcher mBroadcastDispatcher;
- @Mock
private QSTile.State mMockState;
@Mock
private CentralSurfaces mCentralSurfaces;
@@ -132,31 +131,47 @@ public class QSTileHostTest extends SysuiTestCase {
@Mock
private TileLifecycleManager mTileLifecycleManager;
- private Handler mHandler;
- private TestableLooper mLooper;
+ private FakeExecutor mMainExecutor;
+
private QSTileHost mQSTileHost;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mLooper = TestableLooper.get(this);
- mHandler = new Handler(mLooper.getLooper());
+ mMainExecutor = new FakeExecutor(new FakeSystemClock());
+
when(mTileServiceRequestControllerBuilder.create(any()))
.thenReturn(mTileServiceRequestController);
when(mTileLifecycleManagerFactory.create(any(Intent.class), any(UserHandle.class)))
.thenReturn(mTileLifecycleManager);
mSecureSettings = new FakeSettings();
- mSecureSettings.putStringForUser(
- QSTileHost.TILES_SETTING, "", "", false, mUserTracker.getUserId(), false);
- mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
- mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
- mBroadcastDispatcher, mCentralSurfaces, mQSLogger, mUiEventLogger, mUserTracker,
- mSecureSettings, mCustomTileStatePersister, mTileServiceRequestControllerBuilder,
- mTileLifecycleManagerFactory);
+ saveSetting("");
+ mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mMainExecutor,
+ mPluginManager, mTunerService, mAutoTiles, mDumpManager, mCentralSurfaces,
+ mQSLogger, mUiEventLogger, mUserTracker, mSecureSettings, mCustomTileStatePersister,
+ mTileServiceRequestControllerBuilder, mTileLifecycleManagerFactory);
+
+ mSecureSettings.registerContentObserverForUser(SETTING, new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ mMainExecutor.execute(() -> mQSTileHost.onTuningChanged(SETTING, getSetting()));
+ mMainExecutor.runAllReady();
+ }
+ }, mUserTracker.getUserId());
setUpTileFactory();
}
+ private void saveSetting(String value) {
+ mSecureSettings.putStringForUser(
+ SETTING, value, "", false, mUserTracker.getUserId(), false);
+ }
+
+ private String getSetting() {
+ return mSecureSettings.getStringForUser(SETTING, mUserTracker.getUserId());
+ }
+
private void setUpTileFactory() {
when(mMockState.toString()).thenReturn(MOCK_STATE_STRING);
// Only create this kind of tiles
@@ -173,6 +188,10 @@ public class QSTileHostTest extends SysuiTestCase {
return new NotAvailableTile(mQSTileHost);
} else if (CUSTOM_TILE_SPEC.equals(spec)) {
return mCustomTile;
+ } else if ("internet".equals(spec)
+ || "wifi".equals(spec)
+ || "cell".equals(spec)) {
+ return new TestTile1(mQSTileHost);
} else {
return null;
}
@@ -196,14 +215,14 @@ public class QSTileHostTest extends SysuiTestCase {
public void testInvalidSpecUsesDefault() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec2");
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "not-valid");
+ saveSetting("not-valid");
assertEquals(2, mQSTileHost.getTiles().size());
}
@Test
public void testRemoveWifiAndCellularWithoutInternet() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2");
+ saveSetting("wifi, spec1, cell, spec2");
assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
assertEquals("spec1", mQSTileHost.mTileSpecs.get(1));
@@ -212,7 +231,7 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testRemoveWifiAndCellularWithInternet() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2, internet");
+ saveSetting("wifi, spec1, cell, spec2, internet");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
@@ -221,7 +240,7 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testRemoveWifiWithoutInternet() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, wifi, spec2");
+ saveSetting("spec1, wifi, spec2");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
assertEquals("internet", mQSTileHost.mTileSpecs.get(1));
@@ -230,7 +249,7 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testRemoveCellWithInternet() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, spec2, cell, internet");
+ saveSetting("spec1, spec2, cell, internet");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
@@ -239,7 +258,7 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testNoWifiNoCellularNoInternet() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
+ saveSetting("spec1,spec2");
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
assertEquals("spec2", mQSTileHost.mTileSpecs.get(1));
@@ -249,7 +268,7 @@ public class QSTileHostTest extends SysuiTestCase {
public void testSpecWithInvalidDoesNotUseDefault() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec2");
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec2,not-valid");
+ saveSetting("spec2,not-valid");
assertEquals(1, mQSTileHost.getTiles().size());
QSTile element = CollectionUtils.firstOrNull(mQSTileHost.getTiles());
@@ -258,7 +277,7 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testDump() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
+ saveSetting("spec1,spec2");
StringWriter w = new StringWriter();
PrintWriter pw = new PrintWriter(w);
mQSTileHost.dump(pw, new String[]{});
@@ -274,7 +293,7 @@ public class QSTileHostTest extends SysuiTestCase {
public void testDefault() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles_default, "spec1");
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "default");
+ saveSetting("default");
assertEquals(1, mQSTileHost.getTiles().size());
QSTile element = CollectionUtils.firstOrNull(mQSTileHost.getTiles());
assertTrue(element instanceof TestTile1);
@@ -285,7 +304,7 @@ public class QSTileHostTest extends SysuiTestCase {
public void testNoRepeatedSpecs_addTile() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec2");
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
+ saveSetting("spec1,spec2");
mQSTileHost.addTile("spec1");
@@ -298,9 +317,10 @@ public class QSTileHostTest extends SysuiTestCase {
public void testAddTileAtValidPosition() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec3");
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec3");
+ saveSetting("spec1,spec3");
mQSTileHost.addTile("spec2", 1);
+ mMainExecutor.runAllReady();
assertEquals(3, mQSTileHost.mTileSpecs.size());
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -312,9 +332,10 @@ public class QSTileHostTest extends SysuiTestCase {
public void testAddTileAtInvalidPositionAddsToEnd() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec3");
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec3");
+ saveSetting("spec1,spec3");
mQSTileHost.addTile("spec2", 100);
+ mMainExecutor.runAllReady();
assertEquals(3, mQSTileHost.mTileSpecs.size());
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -326,9 +347,10 @@ public class QSTileHostTest extends SysuiTestCase {
public void testAddTileAtEnd() {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles, "spec1,spec3");
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec3");
+ saveSetting("spec1,spec3");
mQSTileHost.addTile("spec2", QSTileHost.POSITION_AT_END);
+ mMainExecutor.runAllReady();
assertEquals(3, mQSTileHost.mTileSpecs.size());
assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -338,9 +360,10 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testNoRepeatedSpecs_customTile() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, CUSTOM_TILE_SPEC);
+ saveSetting(CUSTOM_TILE_SPEC);
mQSTileHost.addTile(CUSTOM_TILE, /* end */ false);
+ mMainExecutor.runAllReady();
assertEquals(1, mQSTileHost.mTileSpecs.size());
assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
@@ -348,9 +371,10 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testAddedAtBeginningOnDefault_customTile() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1"); // seed
+ saveSetting("spec1"); // seed
mQSTileHost.addTile(CUSTOM_TILE);
+ mMainExecutor.runAllReady();
assertEquals(2, mQSTileHost.mTileSpecs.size());
assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
@@ -358,9 +382,10 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testAddedAtBeginning_customTile() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1"); // seed
+ saveSetting("spec1"); // seed
mQSTileHost.addTile(CUSTOM_TILE, /* end */ false);
+ mMainExecutor.runAllReady();
assertEquals(2, mQSTileHost.mTileSpecs.size());
assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(0));
@@ -368,9 +393,10 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testAddedAtEnd_customTile() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1"); // seed
+ saveSetting("spec1"); // seed
mQSTileHost.addTile(CUSTOM_TILE, /* end */ true);
+ mMainExecutor.runAllReady();
assertEquals(2, mQSTileHost.mTileSpecs.size());
assertEquals(CUSTOM_TILE_SPEC, mQSTileHost.mTileSpecs.get(1));
@@ -409,13 +435,13 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testNotAvailableTile_specNotNull() {
- mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "na");
+ saveSetting("na");
verify(mQSLogger, never()).logTileDestroyed(isNull(), anyString());
}
@Test
public void testCustomTileRemoved_stateDeleted() {
- mQSTileHost.changeTiles(List.of(CUSTOM_TILE_SPEC), List.of());
+ mQSTileHost.changeTilesByUser(List.of(CUSTOM_TILE_SPEC), List.of());
verify(mCustomTileStatePersister)
.removeState(new TileServiceKey(CUSTOM_TILE, mQSTileHost.getUserId()));
@@ -423,29 +449,99 @@ public class QSTileHostTest extends SysuiTestCase {
@Test
public void testRemoveTiles() {
- List<String> tiles = List.of("spec1", "spec2", "spec3");
- mQSTileHost.saveTilesToSettings(tiles);
+ saveSetting("spec1,spec2,spec3");
mQSTileHost.removeTiles(List.of("spec1", "spec2"));
+ mMainExecutor.runAllReady();
assertEquals(List.of("spec3"), mQSTileHost.mTileSpecs);
}
+ @Test
+ public void testTilesRemovedInQuickSuccession() {
+ saveSetting("spec1,spec2,spec3");
+ mQSTileHost.removeTile("spec1");
+ mQSTileHost.removeTile("spec3");
+
+ mMainExecutor.runAllReady();
+ assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ assertEquals("spec2", getSetting());
+ }
+
+ @Test
+ public void testAddTileInMainThread() {
+ saveSetting("spec1,spec2");
+
+ mQSTileHost.addTile("spec3");
+ assertEquals(List.of("spec1", "spec2"), mQSTileHost.mTileSpecs);
+
+ mMainExecutor.runAllReady();
+ assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.mTileSpecs);
+ }
+
+ @Test
+ public void testRemoveTileInMainThread() {
+ saveSetting("spec1,spec2");
+
+ mQSTileHost.removeTile("spec1");
+ assertEquals(List.of("spec1", "spec2"), mQSTileHost.mTileSpecs);
+
+ mMainExecutor.runAllReady();
+ assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ }
+
+ @Test
+ public void testRemoveTilesInMainThread() {
+ saveSetting("spec1,spec2,spec3");
+
+ mQSTileHost.removeTiles(List.of("spec3", "spec1"));
+ assertEquals(List.of("spec1", "spec2", "spec3"), mQSTileHost.mTileSpecs);
+
+ mMainExecutor.runAllReady();
+ assertEquals(List.of("spec2"), mQSTileHost.mTileSpecs);
+ }
+
+ @Test
+ public void testRemoveTileByUserInMainThread() {
+ saveSetting("spec1," + CUSTOM_TILE_SPEC);
+
+ mQSTileHost.removeTileByUser(CUSTOM_TILE);
+ assertEquals(List.of("spec1", CUSTOM_TILE_SPEC), mQSTileHost.mTileSpecs);
+
+ mMainExecutor.runAllReady();
+ assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ }
+
+ @Test
+ public void testNonValidTileNotStoredInSettings() {
+ saveSetting("spec1,not-valid");
+
+ assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals("spec1", getSetting());
+ }
+
+ @Test
+ public void testNotAvailableTileNotStoredInSettings() {
+ saveSetting("spec1,na");
+
+ assertEquals(List.of("spec1"), mQSTileHost.mTileSpecs);
+ assertEquals("spec1", getSetting());
+ }
+
private class TestQSTileHost extends QSTileHost {
TestQSTileHost(Context context, StatusBarIconController iconController,
- QSFactory defaultFactory, Handler mainHandler, Looper bgLooper,
+ QSFactory defaultFactory, Executor mainExecutor,
PluginManager pluginManager, TunerService tunerService,
Provider<AutoTileManager> autoTiles, DumpManager dumpManager,
- BroadcastDispatcher broadcastDispatcher, CentralSurfaces centralSurfaces,
- QSLogger qsLogger, UiEventLogger uiEventLogger, UserTracker userTracker,
- SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister,
+ CentralSurfaces centralSurfaces, QSLogger qsLogger, UiEventLogger uiEventLogger,
+ UserTracker userTracker, SecureSettings secureSettings,
+ CustomTileStatePersister customTileStatePersister,
TileServiceRequestController.Builder tileServiceRequestControllerBuilder,
TileLifecycleManager.Factory tileLifecycleManagerFactory) {
- super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
- tunerService, autoTiles, dumpManager, broadcastDispatcher,
- Optional.of(centralSurfaces), qsLogger, uiEventLogger, userTracker,
- secureSettings, customTileStatePersister, tileServiceRequestControllerBuilder,
- tileLifecycleManagerFactory);
+ super(context, iconController, defaultFactory, mainExecutor, pluginManager,
+ tunerService, autoTiles, dumpManager, Optional.of(centralSurfaces), qsLogger,
+ uiEventLogger, userTracker, secureSettings, customTileStatePersister,
+ tileServiceRequestControllerBuilder, tileLifecycleManagerFactory);
}
@Override
@@ -455,25 +551,16 @@ public class QSTileHostTest extends SysuiTestCase {
@Override
public void onPluginDisconnected(QSFactory plugin) {
}
-
- @Override
- void saveTilesToSettings(List<String> tileSpecs) {
- super.saveTilesToSettings(tileSpecs);
- // After tiles are changed, make sure to call onTuningChanged with the new setting if it
- // changed
- String specs = mSecureSettings.getStringForUser(
- QSTileHost.TILES_SETTING, mUserTracker.getUserId());
- onTuningChanged(TILES_SETTING, specs);
- }
}
+
private class TestTile extends QSTileImpl<QSTile.State> {
protected TestTile(QSHost host) {
super(
host,
- mLooper.getLooper(),
- new Handler(mLooper.getLooper()),
+ mock(Looper.class),
+ mock(Handler.class),
new FalsingManagerFake(),
mock(MetricsLogger.class),
mock(StatusBarStateController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
index 3d53062d7d02..d42cbe3b698a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileAdapterTest.java
@@ -55,6 +55,6 @@ public class TileAdapterTest extends SysuiTestCase {
@Test
public void testResetNotifiesHost() {
mTileAdapter.resetTileSpecs(Collections.emptyList());
- verify(mQSTileHost).changeTiles(any(), any());
+ verify(mQSTileHost).changeTilesByUser(any(), any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 6b7e5b9335f2..471ddfd3f224 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.quicksettings.IQSTileService;
@@ -65,6 +66,7 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Provider;
@@ -130,17 +132,16 @@ public class TileServicesTest extends SysuiTestCase {
.thenReturn(mTileLifecycleManager);
Provider<Handler> provider = () -> new Handler(mTestableLooper.getLooper());
+ Executor executor = new HandlerExecutor(provider.get());
QSTileHost host = new QSTileHost(mContext,
mStatusBarIconController,
mQSFactory,
- provider.get(),
- mTestableLooper.getLooper(),
+ executor,
mPluginManager,
mTunerService,
() -> mAutoTileManager,
mDumpManager,
- mock(BroadcastDispatcher.class),
Optional.of(mCentralSurfaces),
mQSLogger,
mUiEventLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 7687d1204541..dd2b66765fae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -29,7 +29,9 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -59,6 +61,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.KeyguardNotificationSuppressor;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.NotificationStateChangedListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -325,6 +328,38 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
}
@Test
+ public void testUpdateIsPublicMode() {
+ when(mKeyguardStateController.isMethodSecure()).thenReturn(true);
+
+ NotificationStateChangedListener listener = mock(NotificationStateChangedListener.class);
+ mLockscreenUserManager.addNotificationStateChangedListener(listener);
+ mLockscreenUserManager.mCurrentProfiles.append(0, mock(UserInfo.class));
+
+ // first call explicitly sets user 0 to not public; notifies
+ mLockscreenUserManager.updatePublicMode();
+ assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener).onNotificationStateChanged();
+ clearInvocations(listener);
+
+ // calling again has no changes; does not notify
+ mLockscreenUserManager.updatePublicMode();
+ assertFalse(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener, never()).onNotificationStateChanged();
+
+ // Calling again with keyguard now showing makes user 0 public; notifies
+ when(mKeyguardStateController.isShowing()).thenReturn(true);
+ mLockscreenUserManager.updatePublicMode();
+ assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener).onNotificationStateChanged();
+ clearInvocations(listener);
+
+ // calling again has no changes; does not notify
+ mLockscreenUserManager.updatePublicMode();
+ assertTrue(mLockscreenUserManager.isLockscreenPublicMode(0));
+ verify(listener, never()).onNotificationStateChanged();
+ }
+
+ @Test
public void testShowSilentNotifications_settingSaysShow() {
mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
mSettings.putInt(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 90627cb0fa78..25add0da4e71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -24,6 +24,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.google.common.truth.Truth.assertThat;
@@ -31,6 +32,7 @@ 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.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -95,6 +97,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
NotifPipelineFlags mFlags;
@Mock
KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
+ @Mock
+ PendingIntent mPendingIntent;
private NotificationInterruptStateProviderImpl mNotifInterruptionStateProvider;
@@ -422,6 +426,122 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
assertThat(mNotifInterruptionStateProvider.shouldHeadsUp(entry)).isFalse();
}
+ @Test
+ public void testShouldNotFullScreen_notPendingIntent() throws RemoteException {
+ NotificationEntry entry = createNotification(IMPORTANCE_HIGH);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isFalse();
+ verify(mLogger, never()).logNoFullscreen(any(), any());
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+ verify(mLogger, never()).logFullscreen(any(), any());
+ }
+
+ @Test
+ public void testShouldNotFullScreen_notHighImportance() throws RemoteException {
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_DEFAULT, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isFalse();
+ verify(mLogger).logNoFullscreen(entry, "Not important enough");
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+ verify(mLogger, never()).logFullscreen(any(), any());
+ }
+
+ @Test
+ public void testShouldNotFullScreen_isGroupAlertSilenced() throws RemoteException {
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ true);
+ when(mPowerManager.isInteractive()).thenReturn(false);
+ when(mDreamManager.isDreaming()).thenReturn(true);
+ when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isFalse();
+ verify(mLogger, never()).logNoFullscreen(any(), any());
+ verify(mLogger).logNoFullscreenWarning(entry, "GroupAlertBehavior will prevent HUN");
+ verify(mLogger, never()).logFullscreen(any(), any());
+ }
+
+ @Test
+ public void testShouldFullScreen_notInteractive() throws RemoteException {
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(false);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isTrue();
+ verify(mLogger, never()).logNoFullscreen(any(), any());
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+ verify(mLogger).logFullscreen(entry, "Device is not interactive");
+ }
+
+ @Test
+ public void testShouldFullScreen_isDreaming() throws RemoteException {
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(true);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isTrue();
+ verify(mLogger, never()).logNoFullscreen(any(), any());
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+ verify(mLogger).logFullscreen(entry, "Device is dreaming");
+ }
+
+ @Test
+ public void testShouldFullScreen_onKeyguard() throws RemoteException {
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isTrue();
+ verify(mLogger, never()).logNoFullscreen(any(), any());
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+ verify(mLogger).logFullscreen(entry, "Keyguard is showing");
+ }
+
+ @Test
+ public void testShouldNotFullScreen_willHun() throws RemoteException {
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mPowerManager.isScreenOn()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isFalse();
+ verify(mLogger).logNoFullscreen(entry, "Expected to HUN");
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+ verify(mLogger, never()).logFullscreen(any(), any());
+ }
+
+ @Test
+ public void testShouldFullScreen_packageSnoozed() throws RemoteException {
+ NotificationEntry entry = createFsiNotification(IMPORTANCE_HIGH, /* silenced */ false);
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ when(mPowerManager.isScreenOn()).thenReturn(true);
+ when(mDreamManager.isDreaming()).thenReturn(false);
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+ when(mHeadsUpManager.isSnoozed("a")).thenReturn(true);
+
+ assertThat(mNotifInterruptionStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry))
+ .isTrue();
+ verify(mLogger).logNoHeadsUpPackageSnoozed(entry.getSbn());
+ verify(mLogger, never()).logNoFullscreen(any(), any());
+ verify(mLogger, never()).logNoFullscreenWarning(any(), any());
+ verify(mLogger).logFullscreen(entry, "Expected not to HUN");
+ }
+
/**
* Bubbles can happen.
*/
@@ -526,6 +646,10 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.setContentText("content text")
.build();
+ return createNotification(importance, n);
+ }
+
+ private NotificationEntry createNotification(int importance, Notification n) {
return new NotificationEntryBuilder()
.setPkg("a")
.setOpPkg("a")
@@ -536,6 +660,20 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase {
.build();
}
+ private NotificationEntry createFsiNotification(int importance, boolean silent) {
+ Notification n = new Notification.Builder(getContext(), "a")
+ .setContentTitle("title")
+ .setContentText("content text")
+ .setFullScreenIntent(mPendingIntent, true)
+ .setGroup("fsi")
+ .setGroupAlertBehavior(silent
+ ? Notification.GROUP_ALERT_SUMMARY
+ : Notification.GROUP_ALERT_ALL)
+ .build();
+
+ return createNotification(importance, n);
+ }
+
private final NotificationInterruptSuppressor
mSuppressAwakeHeadsUp =
new NotificationInterruptSuppressor() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 371119cc6d01..4ccbc6d45e63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -490,7 +490,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
mAutoTileManager.init();
when(mAutoAddTracker.isAdded(TEST_CUSTOM_SAFETY_SPEC)).thenReturn(true);
mAutoTileManager.mSafetyCallback.onSafetyCenterEnableChanged(false);
- verify(mQsTileHost, times(1)).removeTile(safetyComponent);
+ verify(mQsTileHost, times(1)).removeTile(TEST_CUSTOM_SAFETY_SPEC);
}
@Test
diff --git a/services/accessibility/OWNERS b/services/accessibility/OWNERS
index 2b9f179b832d..6e76a207e06f 100644
--- a/services/accessibility/OWNERS
+++ b/services/accessibility/OWNERS
@@ -2,3 +2,5 @@ pweaver@google.com
sallyyuen@google.com
ryanlwlin@google.com
fuego@google.com
+danielnorman@google.com
+aarmaly@google.com
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 9b29bae1fc46..9e428877d9dc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -176,6 +176,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
private boolean mSendMotionEvents;
+ private SparseArray<Boolean> mServiceDetectsGestures = new SparseArray<>(0);
boolean mRequestFilterKeyEvents;
boolean mRetrieveInteractiveWindows;
@@ -2344,9 +2345,17 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
}
public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) {
+ mServiceDetectsGestures.put(displayId, mode);
mSystemSupport.setServiceDetectsGesturesEnabled(displayId, mode);
}
+ public boolean isServiceDetectsGesturesEnabled(int displayId) {
+ if (mServiceDetectsGestures.contains(displayId)) {
+ return mServiceDetectsGestures.get(displayId);
+ }
+ return false;
+ }
+
public void requestTouchExploration(int displayId) {
mSystemSupport.requestTouchExploration(displayId);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 75724bffabf8..952e85a310bc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -176,6 +176,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
private int mEnabledFeatures;
+ // Display-specific features
+ private SparseArray<Boolean> mServiceDetectsGestures = new SparseArray<>();
private final SparseArray<EventStreamState> mMouseStreamStates = new SparseArray<>(0);
private final SparseArray<EventStreamState> mTouchScreenStreamStates = new SparseArray<>(0);
@@ -458,7 +460,9 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
final Context displayContext = mContext.createDisplayContext(display);
final int displayId = display.getDisplayId();
-
+ if (!mServiceDetectsGestures.contains(displayId)) {
+ mServiceDetectsGestures.put(displayId, false);
+ }
if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) {
if (mAutoclickController == null) {
mAutoclickController = new AutoclickController(
@@ -481,6 +485,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
if ((mEnabledFeatures & FLAG_SEND_MOTION_EVENTS) != 0) {
explorer.setSendMotionEventsEnabled(true);
}
+ explorer.setServiceDetectsGestures(mServiceDetectsGestures.get(displayId));
addFirstEventHandler(displayId, explorer);
mTouchExplorer.put(displayId, explorer);
}
@@ -565,7 +570,8 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
mTouchExplorer.remove(displayId);
}
- final MagnificationGestureHandler handler = mMagnificationGestureHandler.get(displayId);
+ final MagnificationGestureHandler handler =
+ mMagnificationGestureHandler.get(displayId);
if (handler != null) {
handler.onDestroy();
mMagnificationGestureHandler.remove(displayId);
@@ -897,8 +903,12 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
if (mTouchExplorer.contains(displayId)) {
mTouchExplorer.get(displayId).setServiceDetectsGestures(mode);
}
+ mServiceDetectsGestures.put(displayId, mode);
}
+ public void resetServiceDetectsGestures() {
+ mServiceDetectsGestures.clear();
+ }
public void requestTouchExploration(int displayId) {
if (mTouchExplorer.contains(displayId)) {
mTouchExplorer.get(displayId).requestTouchExploration();
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 9a1d29554ad6..cdfa0c0411e4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -728,7 +728,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
- intentFilter.addAction(Intent.ACTION_USER_PRESENT);
intentFilter.addAction(Intent.ACTION_SETTING_RESTORED);
mContext.registerReceiverAsUser(new BroadcastReceiver() {
@@ -746,14 +745,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
- // We will update when the automation service dies.
- synchronized (mLock) {
- AccessibilityUserState userState = getCurrentUserStateLocked();
- if (readConfigurationForUserStateLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
- }
} else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
@@ -1730,31 +1721,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
private boolean scheduleNotifyMotionEvent(MotionEvent event) {
+ boolean result = false;
+ int displayId = event.getDisplayId();
synchronized (mLock) {
AccessibilityUserState state = getCurrentUserStateLocked();
for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
AccessibilityServiceConnection service = state.mBoundServices.get(i);
- if (service.mRequestTouchExplorationMode) {
+ if (service.isServiceDetectsGesturesEnabled(displayId)) {
service.notifyMotionEvent(event);
- return true;
+ result = true;
}
}
}
- return false;
+ return result;
}
private boolean scheduleNotifyTouchState(int displayId, int touchState) {
+ boolean result = false;
synchronized (mLock) {
AccessibilityUserState state = getCurrentUserStateLocked();
for (int i = state.mBoundServices.size() - 1; i >= 0; i--) {
AccessibilityServiceConnection service = state.mBoundServices.get(i);
- if (service.mRequestTouchExplorationMode) {
+ if (service.isServiceDetectsGesturesEnabled(displayId)) {
service.notifyTouchState(displayId, touchState);
- return true;
+ result = true;
}
}
}
- return false;
+ return result;
}
private void notifyClearAccessibilityCacheLocked() {
@@ -2323,12 +2317,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (userState.isPerformGesturesEnabledLocked()) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_INJECT_MOTION_EVENTS;
}
+
if (flags != 0) {
if (!mHasInputFilter) {
mHasInputFilter = true;
if (mInputFilter == null) {
- mInputFilter = new AccessibilityInputFilter(mContext,
- AccessibilityManagerService.this);
+ mInputFilter =
+ new AccessibilityInputFilter(
+ mContext, AccessibilityManagerService.this);
}
inputFilter = mInputFilter;
setInputFilter = true;
@@ -2338,6 +2334,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (mHasInputFilter) {
mHasInputFilter = false;
mInputFilter.setUserAndEnabledFeatures(userState.mUserId, 0);
+ mInputFilter.resetServiceDetectsGestures();
+ if (userState.isTouchExplorationEnabledLocked()) {
+ // Service gesture detection is turned on and off on a per-display
+ // basis.
+ final ArrayList<Display> displays = getValidDisplayList();
+ for (Display display : displays) {
+ int displayId = display.getDisplayId();
+ boolean mode = userState.isServiceDetectsGesturesEnabled(displayId);
+ mInputFilter.setServiceDetectsGesturesEnabled(displayId, mode);
+ }
+ }
inputFilter = null;
setInputFilter = true;
}
@@ -2653,6 +2660,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
Binder.restoreCallingIdentity(identity);
}
}
+ // Service gesture detection is turned on and off on a per-display
+ // basis.
+ userState.resetServiceDetectsGestures();
+ final ArrayList<Display> displays = getValidDisplayList();
+ for (AccessibilityServiceConnection service: userState.mBoundServices) {
+ for (Display display : displays) {
+ int displayId = display.getDisplayId();
+ if (service.isServiceDetectsGesturesEnabled(displayId)) {
+ userState.setServiceDetectsGesturesEnabled(displayId, true);
+ }
+ }
+ }
userState.setServiceHandlesDoubleTapLocked(serviceHandlesDoubleTapEnabled);
userState.setMultiFingerGesturesLocked(requestMultiFingerGestures);
userState.setTwoFingerPassthroughLocked(requestTwoFingerPassthrough);
@@ -4313,6 +4332,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
private void setServiceDetectsGesturesInternal(int displayId, boolean mode) {
synchronized (mLock) {
+ getCurrentUserStateLocked().setServiceDetectsGesturesEnabled(displayId, mode);
if (mHasInputFilter && mInputFilter != null) {
mInputFilter.setServiceDetectsGesturesEnabled(displayId, mode);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 55dc196fc18d..a0fc8d30f64c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -44,6 +44,7 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;
@@ -118,6 +119,7 @@ class AccessibilityUserState {
private boolean mRequestMultiFingerGestures;
private boolean mRequestTwoFingerPassthrough;
private boolean mSendMotionEventsEnabled;
+ private SparseArray<Boolean> mServiceDetectsGestures = new SparseArray<>(0);
private int mUserInteractiveUiTimeout;
private int mUserNonInteractiveUiTimeout;
private int mNonInteractiveUiTimeout = 0;
@@ -987,4 +989,18 @@ class AccessibilityUserState {
mFocusStrokeWidth = strokeWidth;
mFocusColor = color;
}
+
+ public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) {
+ mServiceDetectsGestures.put(displayId, mode);
+ }
+
+ public void resetServiceDetectsGestures() {
+ mServiceDetectsGestures.clear();
+ }
+ public boolean isServiceDetectsGesturesEnabled(int displayId) {
+ if (mServiceDetectsGestures.contains(displayId)) {
+ return mServiceDetectsGestures.get(displayId);
+ }
+ return false;
+ }
}
diff --git a/services/companion/java/com/android/server/companion/virtual/OWNERS b/services/companion/java/com/android/server/companion/virtual/OWNERS
index b3c3a4d3a192..5e8291fe5587 100644
--- a/services/companion/java/com/android/server/companion/virtual/OWNERS
+++ b/services/companion/java/com/android/server/companion/virtual/OWNERS
@@ -2,3 +2,4 @@ set noparent
ogunwale@google.com
michaelwr@google.com
+vladokom@google.com \ No newline at end of file
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 2015dc929a59..804d7f3b7d60 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -165,9 +165,14 @@ public class NetworkTimeUpdateService extends Binder {
mContext.enforceCallingPermission(
android.Manifest.permission.SET_TIME, "clear latest network time");
- mTime.clearCachedTimeResult();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mTime.clearCachedTimeResult();
- mLocalLog.log("clearTimeForTests");
+ mLocalLog.log("clearTimeForTests");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
/**
@@ -181,15 +186,19 @@ public class NetworkTimeUpdateService extends Binder {
mContext.enforceCallingPermission(
android.Manifest.permission.SET_TIME, "force network time refresh");
- boolean success = mTime.forceRefresh();
- mLocalLog.log("forceRefreshForTests: success=" + success);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ boolean success = mTime.forceRefresh();
+ mLocalLog.log("forceRefreshForTests: success=" + success);
- if (success) {
- makeNetworkTimeSuggestion(mTime.getCachedTimeResult(),
- "Origin: NetworkTimeUpdateService: forceRefreshForTests");
+ if (success) {
+ makeNetworkTimeSuggestion(mTime.getCachedTimeResult(),
+ "Origin: NetworkTimeUpdateService: forceRefreshForTests");
+ }
+ return success;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
-
- return success;
}
/**
@@ -201,10 +210,15 @@ public class NetworkTimeUpdateService extends Binder {
mContext.enforceCallingPermission(
android.Manifest.permission.SET_TIME, "set NTP server config for tests");
- mLocalLog.log("Setting server config for tests: hostname=" + hostname
- + ", port=" + port
- + ", timeout=" + timeout);
- mTime.setServerConfigForTests(hostname, port, timeout);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mLocalLog.log("Setting server config for tests: hostname=" + hostname
+ + ", port=" + port
+ + ", timeout=" + timeout);
+ mTime.setServerConfigForTests(hostname, port, timeout);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
private void onPollNetworkTime(int event) {
diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS
index 6ff8e36a1f82..c4418592226d 100644
--- a/services/core/java/com/android/server/OWNERS
+++ b/services/core/java/com/android/server/OWNERS
@@ -16,6 +16,7 @@ per-file ServiceWatcher.java = sooniln@google.com
# Health
per-file BatteryService.java = file:platform/hardware/interfaces:/health/aidl/OWNERS
+per-file *Accessibility* = file:/services/accessibility/OWNERS
per-file *Alarm* = file:/apex/jobscheduler/OWNERS
per-file *AppOp* = file:/core/java/android/permission/OWNERS
per-file *Battery* = file:/BATTERY_STATS_OWNERS
@@ -35,6 +36,8 @@ per-file NetIdManager.java = file:/services/core/java/com/android/server/net/OWN
per-file PackageWatchdog.java, RescueParty.java = file:/services/core/java/com/android/server/rollback/OWNERS
per-file PinnerService.java = file:/apct-tests/perftests/OWNERS
per-file RescueParty.java = fdunlap@google.com, shuc@google.com
+per-file SystemClockTime.java = file:/services/core/java/com/android/server/timedetector/OWNERS
+per-file SystemTimeZone.java = file:/services/core/java/com/android/server/timezonedetector/OWNERS
per-file TelephonyRegistry.java = file:/telephony/OWNERS
per-file UiModeManagerService.java = file:/packages/SystemUI/OWNERS
per-file VcnManagementService.java = file:/services/core/java/com/android/server/vcn/OWNERS
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index b86fe7ec4c32..f7b05f2b895a 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -373,7 +373,7 @@ class StorageManagerService extends IStorageManager.Stub
private volatile boolean mChargingRequired;
private volatile int mMinGCSleepTime;
private volatile int mTargetDirtyRatio;
- private volatile boolean mNeedGC;
+ private volatile boolean mNeedGC = true;
private volatile boolean mPassedLifetimeThresh;
// Tracking storage write amounts in one period
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 7d8c19f41ae4..6b731c319c4b 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1820,6 +1820,14 @@ public class AccountManagerService
if (account == null) {
return false;
}
+ if (account.name != null && account.name.length() > 200) {
+ Log.w(TAG, "Account cannot be added - Name longer than 200 chars");
+ return false;
+ }
+ if (account.type != null && account.type.length() > 200) {
+ Log.w(TAG, "Account cannot be added - Name longer than 200 chars");
+ return false;
+ }
if (!isLocalUnlockedUser(accounts.userId)) {
Log.w(TAG, "Account " + account.toSafeString() + " cannot be added - user "
+ accounts.userId + " is locked. callingUid=" + callingUid);
@@ -2065,6 +2073,10 @@ public class AccountManagerService
+ ", pid " + Binder.getCallingPid());
}
if (accountToRename == null) throw new IllegalArgumentException("account is null");
+ if (newName != null && newName.length() > 200) {
+ Log.e(TAG, "renameAccount failed - account name longer than 200");
+ throw new IllegalArgumentException("account name longer than 200");
+ }
int userId = UserHandle.getCallingUserId();
if (!isAccountManagedByCaller(accountToRename.type, callingUid, userId)) {
String msg = String.format(
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 6076eb1f69ee..7a09ce722f94 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -2790,13 +2790,6 @@ public final class AppRestrictionController {
if (isOnSystemDeviceIdleAllowlist(uid)) {
return REASON_SYSTEM_ALLOW_LISTED;
}
- if (isOnDeviceIdleAllowlist(uid)) {
- return REASON_ALLOWLISTED_PACKAGE;
- }
- final ActivityManagerInternal am = mInjector.getActivityManagerInternal();
- if (am.isAssociatedCompanionApp(UserHandle.getUserId(uid), uid)) {
- return REASON_COMPANION_DEVICE_MANAGER;
- }
if (UserManager.isDeviceInDemoMode(mContext)) {
return REASON_DEVICE_DEMO_MODE;
}
@@ -2805,6 +2798,7 @@ public final class AppRestrictionController {
.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL, userId)) {
return REASON_DISALLOW_APPS_CONTROL;
}
+ final ActivityManagerInternal am = mInjector.getActivityManagerInternal();
if (am.isDeviceOwner(uid)) {
return REASON_DEVICE_OWNER;
}
@@ -2822,14 +2816,9 @@ public final class AppRestrictionController {
final AppOpsManager appOpsManager = mInjector.getAppOpsManager();
final PackageManagerInternal pm = mInjector.getPackageManagerInternal();
final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
+ // Check each packages to see if any of them is in the "fixed" exemption cases.
for (String pkg : packages) {
- if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN,
- uid, pkg) == AppOpsManager.MODE_ALLOWED) {
- return REASON_OP_ACTIVATE_VPN;
- } else if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN,
- uid, pkg) == AppOpsManager.MODE_ALLOWED) {
- return REASON_OP_ACTIVATE_PLATFORM_VPN;
- } else if (isSystemModule(pkg)) {
+ if (isSystemModule(pkg)) {
return REASON_SYSTEM_MODULE;
} else if (isCarrierApp(pkg)) {
return REASON_CARRIER_PRIVILEGED_APP;
@@ -2843,6 +2832,16 @@ public final class AppRestrictionController {
return REASON_ACTIVE_DEVICE_ADMIN;
}
}
+ // Loop the packages again, and check the user-configurable exemptions.
+ for (String pkg : packages) {
+ if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_VPN,
+ uid, pkg) == AppOpsManager.MODE_ALLOWED) {
+ return REASON_OP_ACTIVATE_VPN;
+ } else if (appOpsManager.checkOpNoThrow(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN,
+ uid, pkg) == AppOpsManager.MODE_ALLOWED) {
+ return REASON_OP_ACTIVATE_PLATFORM_VPN;
+ }
+ }
}
if (isRoleHeldByUid(RoleManager.ROLE_DIALER, uid)) {
return REASON_ROLE_DIALER;
@@ -2850,6 +2849,12 @@ public final class AppRestrictionController {
if (isRoleHeldByUid(RoleManager.ROLE_EMERGENCY, uid)) {
return REASON_ROLE_EMERGENCY;
}
+ if (isOnDeviceIdleAllowlist(uid)) {
+ return REASON_ALLOWLISTED_PACKAGE;
+ }
+ if (am.isAssociatedCompanionApp(UserHandle.getUserId(uid), uid)) {
+ return REASON_COMPANION_DEVICE_MANAGER;
+ }
return REASON_DENIED;
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 178b6bbe755e..eb6a3b3a3cea 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -27,6 +27,7 @@ import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
+import static android.os.Process.getAdvertisedMem;
import static android.os.Process.getFreeMemory;
import static android.os.Process.getTotalMemory;
import static android.os.Process.killProcessQuiet;
@@ -1524,6 +1525,7 @@ public final class ProcessList {
void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
final long homeAppMem = getMemLevel(HOME_APP_ADJ);
final long cachedAppMem = getMemLevel(CACHED_APP_MIN_ADJ);
+ outInfo.advertisedMem = getAdvertisedMem();
outInfo.availMem = getFreeMemory();
outInfo.totalMem = getTotalMemory();
outInfo.threshold = homeAppMem;
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index cee34d5568b5..252a00bace20 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -17,7 +17,6 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
-import static android.app.ActivityManager.processStateAmToProto;
import android.annotation.IntDef;
import android.app.IApplicationThread;
@@ -318,12 +317,6 @@ final class ProcessProfileRecord {
origBase.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
pkgList.getPackageListLocked());
- pkgList.forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- processStateAmToProto(ProcessStats.STATE_NOTHING),
- holder.appVersion)
- );
}
origBase.makeInactive();
}
@@ -362,12 +355,6 @@ final class ProcessProfileRecord {
origBase.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), SystemClock.uptimeMillis(),
pkgList.getPackageListLocked());
- pkgList.forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- processStateAmToProto(ProcessStats.STATE_NOTHING),
- holder.appVersion)
- );
}
origBase.makeInactive();
setBaseProcessTracker(null);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 07b6fcdcb0ca..482e6a792a90 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -54,7 +54,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.Zygote;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.wm.WindowProcessController;
import com.android.server.wm.WindowProcessListener;
@@ -1212,12 +1211,6 @@ class ProcessRecord implements WindowProcessListener {
long now = SystemClock.uptimeMillis();
baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), now, mPkgList.getPackageListLocked());
- mPkgList.forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- uid, processName, pkgName,
- ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
- holder.appVersion)
- );
if (numOfPkgs != 1) {
mPkgList.forEachPackageProcessStats(holder -> {
if (holder.state != null && holder.state != baseProcessTracker) {
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 262436d693ec..f0241aa5ed82 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -36,7 +36,6 @@ import android.util.TimeUtils;
import com.android.internal.annotations.CompositeRWLock;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.server.am.PlatformCompatCache.CachedCompatChangeId;
import java.io.PrintWriter;
@@ -599,12 +598,6 @@ final class ProcessStateRecord {
@GuardedBy({"mService", "mProcLock"})
void setReportedProcState(int repProcState) {
mRepProcState = repProcState;
- mApp.getPkgList().forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- ActivityManager.processStateAmToProto(mRepProcState),
- holder.appVersion)
- );
mApp.getWindowProcessController().setReportedProcState(repProcState);
}
@@ -620,12 +613,6 @@ final class ProcessStateRecord {
mRepProcState = newState;
setCurProcState(newState);
setCurRawProcState(newState);
- mApp.getPkgList().forEachPackage((pkgName, holder) ->
- FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_STATE_CHANGED,
- mApp.uid, mApp.processName, pkgName,
- ActivityManager.processStateAmToProto(mRepProcState),
- holder.appVersion)
- );
}
}
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 5b80f40aa2c0..5ddb45ded19e 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -90,6 +90,7 @@ public class SettingsToPropertiesMapper {
DeviceConfig.NAMESPACE_NETD_NATIVE,
DeviceConfig.NAMESPACE_NNAPI_NATIVE,
DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
+ DeviceConfig.NAMESPACE_REMOTE_KEY_PROVISIONING_NATIVE,
DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT,
DeviceConfig.NAMESPACE_STATSD_NATIVE,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index eba9c7a5f14e..8e179b942d1e 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -17,9 +17,12 @@ package com.android.server.audio;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.compat.CompatChanges;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -118,8 +121,39 @@ import java.util.concurrent.atomic.AtomicBoolean;
// TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055
/*package*/ final Object mSetModeLock = new Object();
- /** PID of current audio mode owner communicated by AudioService */
- private int mModeOwnerPid = 0;
+ /** AudioModeInfo contains information on current audio mode owner
+ * communicated by AudioService */
+ /* package */ static final class AudioModeInfo {
+ /** Current audio mode */
+ final int mMode;
+ /** PID of current audio mode owner */
+ final int mPid;
+ /** UID of current audio mode owner */
+ final int mUid;
+
+ AudioModeInfo(int mode, int pid, int uid) {
+ mMode = mode;
+ mPid = pid;
+ mUid = uid;
+ }
+
+ @Override
+ public String toString() {
+ return "AudioModeInfo: mMode=" + AudioSystem.modeToString(mMode)
+ + ", mPid=" + mPid
+ + ", mUid=" + mUid;
+ }
+ };
+
+ private AudioModeInfo mAudioModeOwner = new AudioModeInfo(AudioSystem.MODE_NORMAL, 0, 0);
+
+ /**
+ * Indicates that default communication device is chosen by routing rules in audio policy
+ * manager and not forced by AudioDeviceBroker.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2)
+ public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L;
//-------------------------------------------------------------------
/*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
@@ -187,7 +221,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ void onSystemReady() {
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
- mModeOwnerPid = mAudioService.getModeOwnerPid();
+ mAudioModeOwner = mAudioService.getAudioModeOwner();
mBtHelper.onSystemReady();
}
}
@@ -368,11 +402,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
@GuardedBy("mDeviceStateLock")
private CommunicationRouteClient topCommunicationRouteClient() {
for (CommunicationRouteClient crc : mCommunicationRouteClients) {
- if (crc.getPid() == mModeOwnerPid) {
+ if (crc.getPid() == mAudioModeOwner.mPid) {
return crc;
}
}
- if (!mCommunicationRouteClients.isEmpty() && mModeOwnerPid == 0) {
+ if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0) {
return mCommunicationRouteClients.get(0);
}
return null;
@@ -390,7 +424,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
AudioDeviceAttributes device = crc != null ? crc.getDevice() : null;
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "requestedCommunicationDevice, device: "
- + device + " mode owner pid: " + mModeOwnerPid);
+ + device + " mAudioModeOwner: " + mAudioModeOwner.toString());
}
return device;
}
@@ -774,8 +808,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info);
}
- /*package*/ void postSetModeOwnerPid(int pid, int mode) {
- sendIIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid, mode);
+ /*package*/ void postSetModeOwner(int mode, int pid, int uid) {
+ sendLMsgNoDelay(MSG_I_SET_MODE_OWNER, SENDMSG_REPLACE,
+ new AudioModeInfo(mode, pid, uid));
}
/*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
@@ -1162,7 +1197,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
pw.println(prefix + "mAccessibilityStrategyId: "
+ mAccessibilityStrategyId);
- pw.println("\n" + prefix + "mModeOwnerPid: " + mModeOwnerPid);
+ pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner);
mBtHelper.dump(pw, prefix);
}
@@ -1288,12 +1323,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
break;
case MSG_L_SET_BT_ACTIVE_DEVICE:
- synchronized (mDeviceStateLock) {
- BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
- mDeviceInventory.onSetBtActiveDevice(btInfo,
- (btInfo.mProfile != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
- ? mAudioService.getBluetoothContextualVolumeStream()
- : AudioSystem.STREAM_DEFAULT);
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
+ mDeviceInventory.onSetBtActiveDevice(btInfo,
+ (btInfo.mProfile
+ != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput)
+ ? mAudioService.getBluetoothContextualVolumeStream()
+ : AudioSystem.STREAM_DEFAULT);
+ if (btInfo.mProfile == BluetoothProfile.LE_AUDIO
+ || btInfo.mProfile == BluetoothProfile.HEARING_AID) {
+ onUpdateCommunicationRouteClient("setBluetoothActiveDevice");
+ }
+ }
}
break;
case MSG_BT_HEADSET_CNCT_FAILED:
@@ -1338,11 +1380,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1);
}
break;
- case MSG_I_SET_MODE_OWNER_PID:
+ case MSG_I_SET_MODE_OWNER:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
- mModeOwnerPid = msg.arg1;
- if (msg.arg2 != AudioSystem.MODE_RINGTONE) {
+ mAudioModeOwner = (AudioModeInfo) msg.obj;
+ if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) {
onUpdateCommunicationRouteClient("setNewModeOwner");
}
}
@@ -1504,7 +1546,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_REPORT_NEW_ROUTES = 13;
private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
- private static final int MSG_I_SET_MODE_OWNER_PID = 16;
+ private static final int MSG_I_SET_MODE_OWNER = 16;
private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22;
private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23;
@@ -1826,8 +1868,16 @@ import java.util.concurrent.atomic.AtomicBoolean;
AudioSystem.setParameters("BT_SCO=on");
}
if (preferredCommunicationDevice == null) {
- removePreferredDevicesForStrategySync(mCommunicationStrategyId);
- removePreferredDevicesForStrategySync(mAccessibilityStrategyId);
+ AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice();
+ if (defaultDevice != null) {
+ setPreferredDevicesForStrategySync(
+ mCommunicationStrategyId, Arrays.asList(defaultDevice));
+ setPreferredDevicesForStrategySync(
+ mAccessibilityStrategyId, Arrays.asList(defaultDevice));
+ } else {
+ removePreferredDevicesForStrategySync(mCommunicationStrategyId);
+ removePreferredDevicesForStrategySync(mAccessibilityStrategyId);
+ }
} else {
setPreferredDevicesForStrategySync(
mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
@@ -1856,26 +1906,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
}
+ // @GuardedBy("mSetModeLock")
+ @GuardedBy("mDeviceStateLock")
private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) {
- synchronized (mSetModeLock) {
- synchronized (mDeviceStateLock) {
- boolean wasSpeakerphoneActive = isSpeakerphoneActive();
- mPreferredCommunicationDevice = device;
- updateActiveCommunicationDevice();
- if (wasSpeakerphoneActive != isSpeakerphoneActive()) {
- try {
- mContext.sendBroadcastAsUser(
- new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED)
- .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
- UserHandle.ALL);
- } catch (Exception e) {
- Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e);
- }
- }
- mAudioService.postUpdateRingerModeServiceInt();
- dispatchCommunicationDevice();
+ boolean wasSpeakerphoneActive = isSpeakerphoneActive();
+ mPreferredCommunicationDevice = device;
+ updateActiveCommunicationDevice();
+ if (wasSpeakerphoneActive != isSpeakerphoneActive()) {
+ try {
+ mContext.sendBroadcastAsUser(
+ new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED)
+ .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
+ UserHandle.ALL);
+ } catch (Exception e) {
+ Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e);
}
}
+ mAudioService.postUpdateRingerModeServiceInt();
+ dispatchCommunicationDevice();
}
private CommunicationRouteClient removeCommunicationRouteClient(
@@ -1915,6 +1963,32 @@ import java.util.concurrent.atomic.AtomicBoolean;
return null;
}
+ @GuardedBy("mDeviceStateLock")
+ private boolean communnicationDeviceCompatOn() {
+ return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION
+ && !(CompatChanges.isChangeEnabled(
+ USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid)
+ || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID);
+ }
+
+ @GuardedBy("mDeviceStateLock")
+ AudioDeviceAttributes getDefaultCommunicationDevice() {
+ // For system server (Telecom) and APKs targeting S and above, we let the audio
+ // policy routing rules select the default communication device.
+ // For older APKs, we force Hearing Aid or LE Audio headset when connected as
+ // those APKs cannot select a LE Audio or Hearing Aid device explicitly.
+ AudioDeviceAttributes device = null;
+ if (communnicationDeviceCompatOn()) {
+ // If both LE and Hearing Aid are active (thie should not happen),
+ // priority to Hearing Aid.
+ device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID);
+ if (device == null) {
+ device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET);
+ }
+ }
+ return device;
+ }
+
@Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) {
synchronized (mDeviceStateLock) {
return mDeviceInventory.getDeviceSensorUuid(device);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index c1f496905dba..35da73ef58c0 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -294,6 +294,7 @@ public class AudioDeviceInventory {
}
}
+ // @GuardedBy("AudioDeviceBroker.mSetModeLock")
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
void onSetBtActiveDevice(@NonNull AudioDeviceBroker.BtDeviceInfo btInfo, int streamType) {
if (AudioService.DEBUG_DEVICES) {
@@ -376,7 +377,8 @@ public class AudioDeviceInventory {
makeLeAudioDeviceUnavailable(address, btInfo.mAudioSystemDevice);
} else if (switchToAvailable) {
makeLeAudioDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
- streamType, btInfo.mVolume, btInfo.mAudioSystemDevice,
+ streamType, btInfo.mVolume == -1 ? -1 : btInfo.mVolume * 10,
+ btInfo.mAudioSystemDevice,
"onSetBtActiveDevice");
}
break;
@@ -1526,6 +1528,19 @@ public class AudioDeviceInventory {
return di.mSensorUuid;
}
}
+
+ /* package */ AudioDeviceAttributes getDeviceOfType(int type) {
+ synchronized (mDevicesLock) {
+ for (DeviceInfo di : mConnectedDevices.values()) {
+ if (di.mDeviceType == type) {
+ return new AudioDeviceAttributes(
+ di.mDeviceType, di.mDeviceAddress, di.mDeviceName);
+ }
+ }
+ }
+ return null;
+ }
+
//----------------------------------------------------------
// For tests only
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 56874f74afb1..c69eae3ede76 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3841,7 +3841,7 @@ public class AudioService extends IAudioService.Stub
}
}
- private void setLeAudioVolumeOnModeUpdate(int mode) {
+ private void setLeAudioVolumeOnModeUpdate(int mode, int streamType, int device) {
switch (mode) {
case AudioSystem.MODE_IN_COMMUNICATION:
case AudioSystem.MODE_IN_CALL:
@@ -3857,8 +3857,6 @@ public class AudioService extends IAudioService.Stub
return;
}
- int streamType = getBluetoothContextualVolumeStream(mode);
-
// Currently, DEVICE_OUT_BLE_HEADSET is the only output type for LE_AUDIO profile.
// (See AudioDeviceBroker#createBtDeviceInfo())
int index = mStreamStates[streamType].getIndex(AudioSystem.DEVICE_OUT_BLE_HEADSET);
@@ -3869,6 +3867,7 @@ public class AudioService extends IAudioService.Stub
+ index + " maxIndex=" + maxIndex + " streamType=" + streamType);
}
mDeviceBroker.postSetLeAudioVolumeIndex(index, maxIndex, streamType);
+ mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "setLeAudioVolumeOnModeUpdate");
}
private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
@@ -5053,16 +5052,17 @@ public class AudioService extends IAudioService.Stub
}
/**
- * Return the pid of the current audio mode owner
+ * Return information on the current audio mode owner
* @return 0 if nobody owns the mode
*/
@GuardedBy("mDeviceBroker.mSetModeLock")
- /*package*/ int getModeOwnerPid() {
+ /*package*/ AudioDeviceBroker.AudioModeInfo getAudioModeOwner() {
SetModeDeathHandler hdlr = getAudioModeOwnerHandler();
if (hdlr != null) {
- return hdlr.getPid();
+ return new AudioDeviceBroker.AudioModeInfo(
+ hdlr.getMode(), hdlr.getPid(), hdlr.getUid());
}
- return 0;
+ return new AudioDeviceBroker.AudioModeInfo(AudioSystem.MODE_NORMAL, 0 , 0);
}
/**
@@ -5244,11 +5244,11 @@ public class AudioService extends IAudioService.Stub
// Forcefully set LE audio volume as a workaround, since the value of 'device'
// is not DEVICE_OUT_BLE_* even when BLE is connected.
- setLeAudioVolumeOnModeUpdate(mode);
+ setLeAudioVolumeOnModeUpdate(mode, streamType, device);
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO
// connections not started by the application changing the mode when pid changes
- mDeviceBroker.postSetModeOwnerPid(pid, mode);
+ mDeviceBroker.postSetModeOwner(mode, pid, uid);
} else {
Log.w(TAG, "onUpdateAudioMode: failed to set audio mode to: " + mode);
}
@@ -5575,7 +5575,10 @@ public class AudioService extends IAudioService.Stub
}
return deviceIds.stream().mapToInt(Integer::intValue).toArray();
}
- /** @see AudioManager#setCommunicationDevice(int) */
+ /**
+ * @see AudioManager#setCommunicationDevice(int)
+ * @see AudioManager#clearCommunicationDevice()
+ */
public boolean setCommunicationDevice(IBinder cb, int portId) {
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
@@ -5590,7 +5593,8 @@ public class AudioService extends IAudioService.Stub
throw new IllegalArgumentException("invalid device type " + device.getType());
}
}
- final String eventSource = new StringBuilder("setCommunicationDevice(")
+ final String eventSource = new StringBuilder()
+ .append(device == null ? "clearCommunicationDevice(" : "setCommunicationDevice(")
.append(") from u/pid:").append(uid).append("/")
.append(pid).toString();
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index b3e7e31d37fc..93841fe288e1 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -49,6 +49,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;
/**
@@ -104,11 +105,7 @@ public final class PlaybackActivityMonitor
private static final VolumeShaper.Operation PLAY_SKIP_RAMP =
new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build();
- private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
- // a public client is one that needs an anonymized version of the playback configurations, we
- // keep track of whether there is at least one to know when we need to create the list of
- // playback configurations that do not contain uid/pid/package name information.
- private boolean mHasPublicClients = false;
+ private final ConcurrentLinkedQueue<PlayMonitorClient> mClients = new ConcurrentLinkedQueue<>();
private final Object mPlayerLock = new Object();
@GuardedBy("mPlayerLock")
@@ -458,11 +455,9 @@ public final class PlaybackActivityMonitor
+ DateFormat.getTimeInstance().format(new Date()));
synchronized(mPlayerLock) {
pw.println("\n playback listeners:");
- synchronized(mClients) {
- for (PlayMonitorClient pmc : mClients) {
- pw.print(" " + (pmc.mIsPrivileged ? "(S)" : "(P)")
- + pmc.toString());
- }
+ for (PlayMonitorClient pmc : mClients) {
+ pw.print(" " + (pmc.isPrivileged() ? "(S)" : "(P)")
+ + pmc.toString());
}
pw.println("\n");
// all players
@@ -534,48 +529,33 @@ public final class PlaybackActivityMonitor
* @param iplayerReleased indicates if the change was due to a player being released
*/
private void dispatchPlaybackChange(boolean iplayerReleased) {
- synchronized (mClients) {
- // typical use case, nobody is listening, don't do any work
- if (mClients.isEmpty()) {
- return;
- }
- }
if (DEBUG) { Log.v(TAG, "dispatchPlaybackChange to " + mClients.size() + " clients"); }
final List<AudioPlaybackConfiguration> configsSystem;
- // list of playback configurations for "public consumption". It is only computed if there
+ // list of playback configurations for "public consumption". It is computed lazy if there
// are non-system playback activity listeners.
- final List<AudioPlaybackConfiguration> configsPublic;
+ List<AudioPlaybackConfiguration> configsPublic = null;
synchronized (mPlayerLock) {
if (mPlayers.isEmpty()) {
return;
}
- configsSystem = new ArrayList<AudioPlaybackConfiguration>(mPlayers.values());
+ configsSystem = new ArrayList<>(mPlayers.values());
}
- synchronized (mClients) {
- // was done at beginning of method, but could have changed
- if (mClients.isEmpty()) {
- return;
- }
- configsPublic = mHasPublicClients ? anonymizeForPublicConsumption(configsSystem) : null;
- final Iterator<PlayMonitorClient> clientIterator = mClients.iterator();
- while (clientIterator.hasNext()) {
- final PlayMonitorClient pmc = clientIterator.next();
- try {
- // do not spam the logs if there are problems communicating with this client
- if (pmc.mErrorCount < PlayMonitorClient.MAX_ERRORS) {
- if (pmc.mIsPrivileged) {
- pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsSystem,
- iplayerReleased);
- } else {
- // non-system clients don't have the control interface IPlayer, so
- // they don't need to flush commands when a player was released
- pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsPublic, false);
- }
+
+ final Iterator<PlayMonitorClient> clientIterator = mClients.iterator();
+ while (clientIterator.hasNext()) {
+ final PlayMonitorClient pmc = clientIterator.next();
+ // do not spam the logs if there are problems communicating with this client
+ if (!pmc.reachedMaxErrorCount()) {
+ if (pmc.isPrivileged()) {
+ pmc.dispatchPlaybackConfigChange(configsSystem,
+ iplayerReleased);
+ } else {
+ if (configsPublic == null) {
+ configsPublic = anonymizeForPublicConsumption(configsSystem);
}
- } catch (RemoteException e) {
- pmc.mErrorCount++;
- Log.e(TAG, "Error (" + pmc.mErrorCount +
- ") trying to dispatch playback config change to " + pmc, e);
+ // non-system clients don't have the control interface IPlayer, so
+ // they don't need to flush commands when a player was released
+ pmc.dispatchPlaybackConfigChange(configsPublic, false);
}
}
}
@@ -798,14 +778,9 @@ public final class PlaybackActivityMonitor
if (pcdb == null) {
return;
}
- synchronized(mClients) {
- final PlayMonitorClient pmc = new PlayMonitorClient(pcdb, isPrivileged);
- if (pmc.init()) {
- if (!isPrivileged) {
- mHasPublicClients = true;
- }
- mClients.add(pmc);
- }
+ final PlayMonitorClient pmc = new PlayMonitorClient(pcdb, isPrivileged);
+ if (pmc.init()) {
+ mClients.add(pmc);
}
}
@@ -813,23 +788,14 @@ public final class PlaybackActivityMonitor
if (pcdb == null) {
return;
}
- synchronized(mClients) {
- final Iterator<PlayMonitorClient> clientIterator = mClients.iterator();
- boolean hasPublicClients = false;
- // iterate over the clients to remove the dispatcher to remove, and reevaluate at
- // the same time if we still have a public client.
- while (clientIterator.hasNext()) {
- PlayMonitorClient pmc = clientIterator.next();
- if (pcdb.asBinder().equals(pmc.mDispatcherCb.asBinder())) {
- pmc.release();
- clientIterator.remove();
- } else {
- if (!pmc.mIsPrivileged) {
- hasPublicClients = true;
- }
- }
+ final Iterator<PlayMonitorClient> clientIterator = mClients.iterator();
+ // iterate over the clients to remove the dispatcher
+ while (clientIterator.hasNext()) {
+ PlayMonitorClient pmc = clientIterator.next();
+ if (pmc.equalsDispatcher(pcdb)) {
+ pmc.release();
+ clientIterator.remove();
}
- mHasPublicClients = hasPublicClients;
}
}
@@ -857,24 +823,34 @@ public final class PlaybackActivityMonitor
// can afford to be static because only one PlaybackActivityMonitor ever instantiated
static PlaybackActivityMonitor sListenerDeathMonitor;
- final IPlaybackConfigDispatcher mDispatcherCb;
- final boolean mIsPrivileged;
-
- int mErrorCount = 0;
// number of errors after which we don't update this client anymore to not spam the logs
- static final int MAX_ERRORS = 5;
+ private static final int MAX_ERRORS = 5;
+
+ private final IPlaybackConfigDispatcher mDispatcherCb;
+
+ @GuardedBy("this")
+ private final boolean mIsPrivileged;
+ @GuardedBy("this")
+ private boolean mIsReleased = false;
+ @GuardedBy("this")
+ private int mErrorCount = 0;
PlayMonitorClient(IPlaybackConfigDispatcher pcdb, boolean isPrivileged) {
mDispatcherCb = pcdb;
mIsPrivileged = isPrivileged;
}
+ @Override
public void binderDied() {
Log.w(TAG, "client died");
sListenerDeathMonitor.unregisterPlaybackCallback(mDispatcherCb);
}
- boolean init() {
+ synchronized boolean init() {
+ if (mIsReleased) {
+ // Do not init after release
+ return false;
+ }
try {
mDispatcherCb.asBinder().linkToDeath(this, 0);
return true;
@@ -884,8 +860,43 @@ public final class PlaybackActivityMonitor
}
}
- void release() {
+ synchronized void release() {
mDispatcherCb.asBinder().unlinkToDeath(this, 0);
+ mIsReleased = true;
+ }
+
+ void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
+ boolean flush) {
+ synchronized (this) {
+ if (mIsReleased) {
+ // Do not dispatch anything after release
+ return;
+ }
+ }
+ try {
+ mDispatcherCb.dispatchPlaybackConfigChange(configs, flush);
+ } catch (RemoteException e) {
+ synchronized (this) {
+ mErrorCount++;
+ Log.e(TAG, "Error (" + mErrorCount
+ + ") trying to dispatch playback config change to " + this, e);
+ }
+ }
+ }
+
+ synchronized boolean isPrivileged() {
+ return mIsPrivileged;
+ }
+
+ synchronized boolean reachedMaxErrorCount() {
+ return mErrorCount >= MAX_ERRORS;
+ }
+
+ synchronized boolean equalsDispatcher(IPlaybackConfigDispatcher pcdb) {
+ if (pcdb == null) {
+ return false;
+ }
+ return pcdb.asBinder().equals(mDispatcherCb.asBinder());
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 6a53978175af..6795b6b4158d 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -21,6 +21,7 @@ import static android.Manifest.permission.CONTROL_VPN;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
@@ -51,6 +52,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
import android.net.DnsResolver;
import android.net.INetd;
@@ -234,6 +236,7 @@ public class Vpn {
private final Context mContext;
private final ConnectivityManager mConnectivityManager;
private final AppOpsManager mAppOpsManager;
+ private final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager;
// The context is for specific user which is created from mUserId
private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
@@ -549,6 +552,8 @@ public class Vpn {
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
+ mConnectivityDiagnosticsManager =
+ mContext.getSystemService(ConnectivityDiagnosticsManager.class);
mDeps = deps;
mNms = netService;
mNetd = netd;
@@ -2739,6 +2744,7 @@ public class Vpn {
@Nullable private IkeSessionWrapper mSession;
@Nullable private IkeSessionConnectionInfo mIkeConnectionInfo;
+ @Nullable private VpnConnectivityDiagnosticsCallback mDiagnosticsCallback;
// mMobikeEnabled can only be updated after IKE AUTH is finished.
private boolean mMobikeEnabled = false;
@@ -2797,6 +2803,15 @@ public class Vpn {
mConnectivityManager.registerSystemDefaultNetworkCallback(mNetworkCallback,
new Handler(mLooper));
}
+
+ // DiagnosticsCallback may return more than one alive VPNs, but VPN will filter based on
+ // Network object.
+ final NetworkRequest diagRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_VPN)
+ .removeCapability(NET_CAPABILITY_NOT_VPN).build();
+ mDiagnosticsCallback = new VpnConnectivityDiagnosticsCallback();
+ mConnectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback(
+ diagRequest, mExecutor, mDiagnosticsCallback);
}
private boolean isActiveNetwork(@Nullable Network network) {
@@ -3066,22 +3081,28 @@ public class Vpn {
return;
}
- try {
- if (mSession != null && mMobikeEnabled) {
- // IKE session can schedule a migration event only when IKE AUTH is finished
- // and mMobikeEnabled is true.
- Log.d(
- TAG,
- "Migrate IKE Session with token "
- + mCurrentToken
- + " to network "
- + underlyingNetwork);
- mSession.setNetwork(underlyingNetwork);
- return;
- }
+ if (maybeMigrateIkeSession(underlyingNetwork)) return;
+
+ startIkeSession(underlyingNetwork);
+ }
- Log.d(TAG, "Start new IKE session on network " + underlyingNetwork);
+ boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) {
+ if (mSession == null || !mMobikeEnabled) return false;
+ // IKE session can schedule a migration event only when IKE AUTH is finished
+ // and mMobikeEnabled is true.
+ Log.d(TAG, "Migrate IKE Session with token "
+ + mCurrentToken
+ + " to network "
+ + underlyingNetwork);
+ mSession.setNetwork(underlyingNetwork);
+ return true;
+ }
+
+ private void startIkeSession(@NonNull Network underlyingNetwork) {
+ Log.d(TAG, "Start new IKE session on network " + underlyingNetwork);
+
+ try {
// Clear mInterface to prevent Ikev2VpnRunner being cleared when
// interfaceRemoved() is called.
synchronized (Vpn.this) {
@@ -3169,6 +3190,28 @@ public class Vpn {
mUnderlyingLinkProperties = lp;
}
+ class VpnConnectivityDiagnosticsCallback
+ extends ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
+ // The callback runs in the executor thread.
+ @Override
+ public void onDataStallSuspected(
+ ConnectivityDiagnosticsManager.DataStallReport report) {
+ synchronized (Vpn.this) {
+ // Ignore stale runner.
+ if (mVpnRunner != Vpn.IkeV2VpnRunner.this) return;
+
+ // Handle the report only for current VPN network.
+ if (mNetworkAgent != null
+ && mNetworkAgent.getNetwork().equals(report.getNetwork())) {
+ Log.d(TAG, "Data stall suspected");
+
+ // Trigger MOBIKE.
+ maybeMigrateIkeSession(mActiveNetwork);
+ }
+ }
+ }
+ }
+
/**
* Handles loss of the default underlying network
*
@@ -3463,6 +3506,8 @@ public class Vpn {
resetIkeState();
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+ mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback(
+ mDiagnosticsCallback);
mExecutor.shutdown();
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 6a57e4070f65..070acd0b6183 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1551,8 +1551,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
// done in HighBrightnessModeController.
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
- && ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
- || (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) {
+ && (mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
+ && (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0) {
// We want to scale HDR brightness level with the SDR level
animateValue = mHbmController.getHdrBrightnessValue();
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 7d35fc5c8bd5..f8a74f4f3f55 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -266,10 +266,6 @@ public class HdmiControlService extends SystemService {
// Make sure HdmiCecConfig is instantiated and the XMLs are read.
private HdmiCecConfig mHdmiCecConfig;
- // Last return value of getPhysicalAddress(). Only updated on calls of getPhysicalAddress().
- // Does not represent the current physical address at all times. Not to be used as a cache.
- private int mPhysicalAddress = Constants.INVALID_PHYSICAL_ADDRESS;
-
/**
* Interface to report send result.
*/
@@ -2084,15 +2080,9 @@ public class HdmiControlService extends SystemService {
@Override
public int getPhysicalAddress() {
initBinderCall();
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
- synchronized (mLock) {
- mPhysicalAddress = mHdmiCecNetwork.getPhysicalAddress();
- }
- }
- });
- return mPhysicalAddress;
+ synchronized (mLock) {
+ return mHdmiCecNetwork.getPhysicalAddress();
+ }
}
@Override
diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS
index 7577ee5c9fde..55b0cffb32df 100644
--- a/services/core/java/com/android/server/locksettings/OWNERS
+++ b/services/core/java/com/android/server/locksettings/OWNERS
@@ -1,4 +1,3 @@
+ebiggers@google.com
jaggies@google.com
-kchyn@google.com
rubinxu@google.com
-xunchang@google.com
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a4f10ba05106..018a2fc734b8 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -7072,6 +7072,7 @@ public class NotificationManagerService extends SystemService {
@GuardedBy("mNotificationLock")
void snoozeLocked(NotificationRecord r) {
+ final List<NotificationRecord> recordsToSnooze = new ArrayList<>();
if (r.getSbn().isGroup()) {
final List<NotificationRecord> groupNotifications =
findCurrentAndSnoozedGroupNotificationsLocked(
@@ -7080,8 +7081,8 @@ public class NotificationManagerService extends SystemService {
if (r.getNotification().isGroupSummary()) {
// snooze all children
for (int i = 0; i < groupNotifications.size(); i++) {
- if (mKey != groupNotifications.get(i).getKey()) {
- snoozeNotificationLocked(groupNotifications.get(i));
+ if (!mKey.equals(groupNotifications.get(i).getKey())) {
+ recordsToSnooze.add(groupNotifications.get(i));
}
}
} else {
@@ -7091,8 +7092,8 @@ public class NotificationManagerService extends SystemService {
if (groupNotifications.size() == 2) {
// snooze summary and the one child
for (int i = 0; i < groupNotifications.size(); i++) {
- if (mKey != groupNotifications.get(i).getKey()) {
- snoozeNotificationLocked(groupNotifications.get(i));
+ if (!mKey.equals(groupNotifications.get(i).getKey())) {
+ recordsToSnooze.add(groupNotifications.get(i));
}
}
}
@@ -7100,7 +7101,15 @@ public class NotificationManagerService extends SystemService {
}
}
// snooze the notification
- snoozeNotificationLocked(r);
+ recordsToSnooze.add(r);
+
+ if (mSnoozeHelper.canSnooze(recordsToSnooze.size())) {
+ for (int i = 0; i < recordsToSnooze.size(); i++) {
+ snoozeNotificationLocked(recordsToSnooze.get(i));
+ }
+ } else {
+ Log.w(TAG, "Cannot snooze " + r.getKey() + ": too many snoozed notifications");
+ }
}
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 7f265df3f416..15d7c1e7a210 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -62,6 +62,8 @@ import java.util.Set;
public class SnoozeHelper {
public static final int XML_SNOOZED_NOTIFICATION_VERSION = 1;
+ static final int CONCURRENT_SNOOZE_LIMIT = 500;
+
protected static final String XML_TAG_NAME = "snoozed-notifications";
private static final String XML_SNOOZED_NOTIFICATION = "notification";
@@ -135,6 +137,15 @@ public class SnoozeHelper {
}
}
+ protected boolean canSnooze(int numberToSnooze) {
+ synchronized (mLock) {
+ if ((mPackages.size() + numberToSnooze) > CONCURRENT_SNOOZE_LIMIT) {
+ return false;
+ }
+ }
+ return true;
+ }
+
@NonNull
protected Long getSnoozeTimeForUnpostedNotification(int userId, String pkg, String key) {
Long time = null;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 9e0c97502c4f..2b00ad7c5cd7 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -330,7 +330,8 @@ public class ZenModeHelper {
int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
+ getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
+ 1;
- if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE
+ int newPackageRuleCount = getPackageRuleCount(pkg) + 1;
+ if (newPackageRuleCount > RULE_LIMIT_PER_PACKAGE
|| (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
throw new IllegalArgumentException("Rule instance limit exceeded");
}
@@ -511,6 +512,23 @@ public class ZenModeHelper {
return count;
}
+ // Equivalent method to getCurrentInstanceCount, but for all rules associated with a specific
+ // package rather than a condition provider service or activity.
+ private int getPackageRuleCount(String pkg) {
+ if (pkg == null) {
+ return 0;
+ }
+ int count = 0;
+ synchronized (mConfig) {
+ for (ZenRule rule : mConfig.automaticRules.values()) {
+ if (pkg.equals(rule.getPkg())) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
public boolean canManageAutomaticZenRule(ZenRule rule) {
final int callingUid = Binder.getCallingUid();
if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 1eb74facb840..46691a61930e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -314,6 +314,8 @@ class PackageManagerShellCommand extends ShellCommand {
return runRemoveUser();
case "set-user-restriction":
return runSetUserRestriction();
+ case "supports-multiple-users":
+ return runSupportsMultipleUsers();
case "get-max-users":
return runGetMaxUsers();
case "get-max-running-users":
@@ -3014,6 +3016,12 @@ class PackageManagerShellCommand extends ShellCommand {
return 0;
}
+ public int runSupportsMultipleUsers() {
+ getOutPrintWriter().println("Is multiuser supported: "
+ + UserManager.supportsMultipleUsers());
+ return 0;
+ }
+
public int runGetMaxUsers() {
getOutPrintWriter().println("Maximum supported users: "
+ UserManager.getMaxSupportedUsers());
diff --git a/services/core/java/com/android/server/resources/OWNERS b/services/core/java/com/android/server/resources/OWNERS
new file mode 100644
index 000000000000..7460a14182e5
--- /dev/null
+++ b/services/core/java/com/android/server/resources/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 568761
+
+patb@google.com
+zyy@google.com
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index d0b058b4c8f2..e197319707e3 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1337,6 +1337,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
FgThread.getHandler().removeCallbacks(mResetRunnable);
mContext.getMainThreadHandler().removeCallbacks(mTryToRebindRunnable);
+ mContext.getMainThreadHandler().removeCallbacks(mDisconnectRunnable);
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ab936a6954d6..83687e9ebccd 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4884,8 +4884,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
ActivityOptions takeOptions() {
if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
+ Debug.getCallers(6));
+ if (mPendingOptions == null) return null;
final ActivityOptions opts = mPendingOptions;
mPendingOptions = null;
+ // Strip sensitive information from options before sending it to app.
+ opts.setRemoteTransition(null);
+ opts.setRemoteAnimationAdapter(null);
return opts;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d190b4f07121..8d831d72c05b 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1441,6 +1441,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
a.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
a.resizeMode = RESIZE_MODE_UNRESIZEABLE;
+ a.configChanges = ActivityInfo.CONFIG_ORIENTATION;
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchActivityType(ACTIVITY_TYPE_DREAM);
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index f83173bd46c0..0bb773ae5e41 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -220,6 +220,11 @@ public class StartingSurfaceController {
// Attempt to add starting window from the top-most activity.
for (int i = mDeferringAddStartActivities.size() - 1; i >= 0; --i) {
final DeferringStartingWindowRecord next = mDeferringAddStartActivities.get(i);
+ if (next.mDeferring.getTask() == null) {
+ Slog.e(TAG, "No task exists: " + next.mDeferring.shortComponentName
+ + " parent: " + next.mDeferring.getParent());
+ continue;
+ }
next.mDeferring.showStartingWindow(next.mPrev, mInitNewTask, mInitTaskSwitch,
mInitProcessRunning, true /* startActivity */, next.mSource, topOptions);
// If one succeeds, it is done.
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 1b0c01816f73..9050d79d714f 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1695,7 +1695,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev);
prev = prev.completeFinishing(false /* updateVisibility */,
"completePausedLocked");
- } else if (prev.hasProcess()) {
+ } else if (prev.attachedToProcess()) {
ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s "
+ "wasStopping=%b visibleRequested=%b", prev, wasStopping,
prev.mVisibleRequested);
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 9abf107c780a..2584b86f53db 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -12,6 +12,7 @@ per-file com_android_server_power_PowerManagerService.* = michaelwr@google.com,
per-file com_android_server_am_BatteryStatsService.cpp = file:/BATTERY_STATS_OWNERS
per-file Android.bp = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
+per-file com_android_server_SystemClock* = file:/services/core/java/com/android/server/timedetector/OWNERS
per-file com_android_server_Usb* = file:/services/usb/OWNERS
per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
diff --git a/services/core/jni/com_android_server_companion_virtual_InputController.cpp b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
index 8197b67355d4..daca1531d41f 100644
--- a/services/core/jni/com_android_server_companion_virtual_InputController.cpp
+++ b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
@@ -21,6 +21,7 @@
#include <android/keycodes.h>
#include <errno.h>
#include <fcntl.h>
+#include <input/Input.h>
#include <linux/uinput.h>
#include <math.h>
#include <nativehelper/JNIHelp.h>
@@ -271,6 +272,14 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno));
return -errno;
}
+ uinput_abs_setup slotAbsSetup;
+ slotAbsSetup.code = ABS_MT_SLOT;
+ slotAbsSetup.absinfo.maximum = MAX_POINTERS;
+ slotAbsSetup.absinfo.minimum = 0;
+ if (ioctl(fd, UI_ABS_SETUP, &slotAbsSetup) != 0) {
+ ALOGE("Error creating touchscreen uinput slots: %s", strerror(errno));
+ return -errno;
+ }
}
if (ioctl(fd, UI_DEV_SETUP, &setup) != 0) {
ALOGE("Error creating uinput device: %s", strerror(errno));
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 6196c49c88ce..9c9b363b948e 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1287,8 +1287,8 @@ int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage,
bp.set_allocated_dest_path(&target);
bp.set_allocated_source_subdir(&source);
const auto metadata = bp.SerializeAsString();
- bp.release_dest_path();
- bp.release_source_subdir();
+ static_cast<void>(bp.release_dest_path());
+ static_cast<void>(bp.release_source_subdir());
mdFileName = makeBindMdName();
metadataFullPath = path::join(ifs.root, constants().mount, mdFileName);
auto node = mIncFs->makeFile(ifs.control, metadataFullPath, 0444, idFromMetadata(metadata),
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index 59d96d2393ef..d9d3d62e92e2 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -474,8 +474,8 @@ public:
m.mutable_loader()->set_package_name("com.test");
m.mutable_loader()->set_arguments("com.uri");
const auto metadata = m.SerializeAsString();
- m.mutable_loader()->release_arguments();
- m.mutable_loader()->release_package_name();
+ static_cast<void>(m.mutable_loader()->release_arguments());
+ static_cast<void>(m.mutable_loader()->release_package_name());
return {metadata.begin(), metadata.end()};
}
RawMetadata getStorageMetadata(const Control& control, std::string_view path) {
@@ -492,8 +492,8 @@ public:
bp.set_allocated_dest_path(&destPath);
bp.set_allocated_source_subdir(&srcPath);
const auto metadata = bp.SerializeAsString();
- bp.release_source_subdir();
- bp.release_dest_path();
+ static_cast<void>(bp.release_source_subdir());
+ static_cast<void>(bp.release_dest_path());
return std::vector<char>(metadata.begin(), metadata.end());
}
};
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index b9d6b2ccd306..994df2288a5c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -392,7 +392,7 @@ class SuspendPackageHelperTest : PackageHelperTestBase() {
whenever(rule.mocks().appsFilter.getVisibilityAllowList(
any(PackageDataSnapshot::class.java),
argThat { it?.packageName == pkgSetting.packageName }, any(IntArray::class.java),
- any() as ArrayMap<String, out PackageStateInternal>
+ any<ArrayMap<String, out PackageStateInternal>>()
))
.thenReturn(list)
}
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index d5c5745d6680..30ec1632a622 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -39,6 +39,7 @@ import android.accounts.IAccountManagerResponse;
import android.app.AppOpsManager;
import android.app.PropertyInvalidatedCache;
import android.app.INotificationManager;
+import android.app.PropertyInvalidatedCache;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
@@ -253,6 +254,26 @@ public class AccountManagerServiceTest extends AndroidTestCase {
}
@SmallTest
+ public void testCheckAddAccountLongName() throws Exception {
+ unlockSystemUser();
+ String longString = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ + "aaaaa";
+ Account a11 = new Account(longString, AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
+
+ mAms.addAccountExplicitly(
+ a11, /* password= */ "p11", /* extras= */ null, /* callerPackage= */ null);
+
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
+ Account[] accounts = mAms.getAccountsAsUser(null,
+ UserHandle.getCallingUserId(), mContext.getOpPackageName());
+ assertEquals(0, accounts.length);
+ }
+
+
+ @SmallTest
public void testPasswords() throws Exception {
unlockSystemUser();
Account a11 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 709c928dad9c..480ad110f357 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3380,39 +3380,98 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
- public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() throws Exception {
+ public void testSnoozeRunnable_tooManySnoozed_singleNotification() {
final NotificationRecord notification = generateNotificationRecord(
mTestNotificationChannel, 1, null, true);
mService.addNotification(notification);
- when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
+
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
+ when(mSnoozeHelper.canSnooze(1)).thenReturn(false);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
- notification.getKey(), 100, null);
+ notification.getKey(), 100, null);
snoozeNotificationRunnable.run();
- NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
+
+ verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
+ assertThat(mService.getNotificationRecordCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void testSnoozeRunnable_tooManySnoozed_singleGroupChildNotification() {
+ final NotificationRecord notification = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", true);
+ final NotificationRecord notificationChild = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", false);
+ mService.addNotification(notification);
+ mService.addNotification(notificationChild);
+
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
+ when(mSnoozeHelper.canSnooze(2)).thenReturn(false);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mService.new SnoozeNotificationRunnable(
+ notificationChild.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
+ assertThat(mService.getNotificationRecordCount()).isEqualTo(2);
+ }
+
+ @Test
+ public void testSnoozeRunnable_tooManySnoozed_summaryNotification() {
+ final NotificationRecord notification = generateNotificationRecord(
+ mTestNotificationChannel, 1, "group", true);
+ final NotificationRecord notificationChild = generateNotificationRecord(
+ mTestNotificationChannel, 12, "group", false);
+ final NotificationRecord notificationChild2 = generateNotificationRecord(
+ mTestNotificationChannel, 13, "group", false);
+ mService.addNotification(notification);
+ mService.addNotification(notificationChild);
+ mService.addNotification(notificationChild2);
+
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
+ when(mSnoozeHelper.canSnooze(3)).thenReturn(false);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
+ mService.new SnoozeNotificationRunnable(
+ notification.getKey(), 100, null);
+ snoozeNotificationRunnable.run();
+
+ verify(mSnoozeHelper, never()).snooze(any(NotificationRecord.class), anyLong());
+ assertThat(mService.getNotificationRecordCount()).isEqualTo(3);
+ }
+
+ @Test
+ public void testSnoozeRunnable_reSnoozeASingleSnoozedNotification() {
+ final NotificationRecord notification = generateNotificationRecord(
+ mTestNotificationChannel, 1, null, true);
+ mService.addNotification(notification);
+ when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
+
+ NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
notification.getKey(), 100, null);
snoozeNotificationRunnable.run();
+ snoozeNotificationRunnable.run();
// snooze twice
verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
}
@Test
- public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() throws Exception {
+ public void testSnoozeRunnable_reSnoozeASnoozedNotificationWithGroupKey() {
final NotificationRecord notification = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
mService.addNotification(notification);
when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
notification.getKey(), 100, null);
snoozeNotificationRunnable.run();
- NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
- mService.new SnoozeNotificationRunnable(
- notification.getKey(), 100, null);
snoozeNotificationRunnable.run();
// snooze twice
@@ -3430,6 +3489,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mSnoozeHelper.getNotification(any())).thenReturn(notification);
when(mSnoozeHelper.getNotifications(
anyString(), anyString(), anyInt())).thenReturn(new ArrayList<>());
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -3439,8 +3499,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.thenReturn(new ArrayList<>(Arrays.asList(notification, notification2)));
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable2 =
mService.new SnoozeNotificationRunnable(
- notification.getKey(), 100, null);
- snoozeNotificationRunnable.run();
+ notification2.getKey(), 100, null);
+ snoozeNotificationRunnable2.run();
// snooze twice
verify(mSnoozeHelper, times(4)).snooze(any(NotificationRecord.class), anyLong());
@@ -3454,6 +3514,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mTestNotificationChannel, 2, "group", false);
mService.addNotification(grouped);
mService.addNotification(nonGrouped);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -3483,6 +3544,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.addNotification(parent);
mService.addNotification(child);
mService.addNotification(child2);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -3504,6 +3566,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.addNotification(parent);
mService.addNotification(child);
mService.addNotification(child2);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -3529,6 +3592,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mTestNotificationChannel, 2, "group", false);
mService.addNotification(parent);
mService.addNotification(child);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
@@ -3556,6 +3620,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
final NotificationRecord child = generateNotificationRecord(
mTestNotificationChannel, 2, "group", false);
mService.addNotification(child);
+ when(mSnoozeHelper.canSnooze(anyInt())).thenReturn(true);
NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
mService.new SnoozeNotificationRunnable(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 2ae2ef7162a5..8bead5774548 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -15,6 +15,7 @@
*/
package com.android.server.notification;
+import static com.android.server.notification.SnoozeHelper.CONCURRENT_SNOOZE_LIMIT;
import static com.android.server.notification.SnoozeHelper.EXTRA_KEY;
import static junit.framework.Assert.assertEquals;
@@ -281,6 +282,22 @@ public class SnoozeHelperTest extends UiServiceTestCase {
}
@Test
+ public void testSnoozeLimit() {
+ for (int i = 0; i < CONCURRENT_SNOOZE_LIMIT; i++ ) {
+ NotificationRecord r = getNotificationRecord("pkg", i, i+"", UserHandle.SYSTEM);
+
+ assertTrue("cannot snooze record " + i, mSnoozeHelper.canSnooze(1));
+
+ if (i % 2 == 0) {
+ mSnoozeHelper.snooze(r, null);
+ } else {
+ mSnoozeHelper.snooze(r, 9000);
+ }
+ }
+ assertFalse(mSnoozeHelper.canSnooze(1));
+ }
+
+ @Test
public void testCancelByApp() throws Exception {
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index fd1536c5c0f1..4550b56f6fd0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -1622,7 +1622,9 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ZenModeConfig.toScheduleConditionId(si),
new ZenPolicy.Builder().build(),
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+ // We need the package name to be something that's not "android" so there aren't any
+ // existing rules under that package.
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
assertNotNull(id);
}
try {
@@ -1632,12 +1634,41 @@ public class ZenModeHelperTest extends UiServiceTestCase {
ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
new ZenPolicy.Builder().build(),
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
- String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test");
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
fail("allowed too many rules to be created");
} catch (IllegalArgumentException e) {
// yay
}
+ }
+ @Test
+ public void testAddAutomaticZenRule_beyondSystemLimit_differentComponents() {
+ // Make sure the system limit is enforced per-package even with different component provider
+ // names.
+ for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+ ScheduleInfo si = new ScheduleInfo();
+ si.startHour = i;
+ AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+ null,
+ new ComponentName("android", "ScheduleConditionProvider" + i),
+ ZenModeConfig.toScheduleConditionId(si),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ assertNotNull(id);
+ }
+ try {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ null,
+ new ComponentName("android", "ScheduleConditionProviderFinal"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ new ZenPolicy.Builder().build(),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
+ fail("allowed too many rules to be created");
+ } catch (IllegalArgumentException e) {
+ // yay
+ }
}
@Test
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fd738d2b531c..70d82701da66 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8995,7 +8995,8 @@ public class TelephonyManager {
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges})
- * and {@link android.Manifest.permission#ACCESS_FINE_LOCATION}.
+ * and {@link android.Manifest.permission#ACCESS_FINE_LOCATION} if includeLocationData is
+ * set to {@link #INCLUDE_LOCATION_DATA_FINE}.
*
* If the system-wide location switch is off, apps may still call this API, with the
* following constraints:
@@ -9009,7 +9010,10 @@ public class TelephonyManager {
* </ol>
*
* @param includeLocationData Specifies if the caller would like to receive
- * location related information.
+ * location related information. If this parameter is set to
+ * {@link #INCLUDE_LOCATION_DATA_FINE} then the application will be checked for
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission and available
+ * location related information received during network scan will be sent to the caller.
* @param request Contains all the RAT with bands/channels that need to be scanned.
* @param executor The executor through which the callback should be invoked. Since the scan
* request may trigger multiple callbacks and they must be invoked in the same order as
@@ -9020,8 +9024,7 @@ public class TelephonyManager {
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
@RequiresPermission(allOf = {
- android.Manifest.permission.MODIFY_PHONE_STATE,
- Manifest.permission.ACCESS_FINE_LOCATION
+ android.Manifest.permission.MODIFY_PHONE_STATE
})
public @Nullable NetworkScan requestNetworkScan(
@IncludeLocationData int includeLocationData,
diff --git a/tests/Codegen/Android.bp b/tests/Codegen/Android.bp
index ddbf16817b94..7fbe3b37f99e 100644
--- a/tests/Codegen/Android.bp
+++ b/tests/Codegen/Android.bp
@@ -24,6 +24,14 @@ android_test {
plugins: [
"staledataclass-annotation-processor",
],
+ // Exports needed for staledataclass-annotation-processor, see b/139342589.
+ javacflags: [
+ "-J--add-modules=jdk.compiler",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+ "-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+ ],
static_libs: [
"junit",
"hamcrest",
diff --git a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
index 2e515705a253..761efe4a8484 100644
--- a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
+++ b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
@@ -110,7 +110,7 @@ public class FixVibrateSetting extends Activity implements View.OnClickListener
private void test() {
Intent intent = new Intent(this, FixVibrateSetting.class);
- PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
+ PendingIntent pending = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
Notification n = new Notification.Builder(this)
.setSmallIcon(R.drawable.stat_sys_warning)
diff --git a/tests/HandwritingIme/OWNERS b/tests/HandwritingIme/OWNERS
new file mode 100644
index 000000000000..6bb4b17ed4eb
--- /dev/null
+++ b/tests/HandwritingIme/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 34867
+
+include /services/core/java/com/android/server/inputmethod/OWNERS
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index b7c4c5b28168..f2234fb64108 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -51,6 +51,7 @@ java_test_host {
data: [
":com.android.apex.apkrollback.test_v1",
":test.rebootless_apex_v1",
+ ":RollbackTest",
],
}
diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp
index 77f98e88f1eb..a1b888aef934 100644
--- a/tests/TrustTests/Android.bp
+++ b/tests/TrustTests/Android.bp
@@ -24,7 +24,7 @@ android_test {
static_libs: [
"androidx.test.rules",
"androidx.test.ext.junit",
- "androidx.test.uiautomator",
+ "androidx.test.uiautomator_uiautomator",
"mockito-target-minus-junit4",
"servicestests-utils",
"truth-prebuilt",
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 23f6c88aad91..3787f3b96f08 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -51,8 +51,10 @@ std::optional<ResourceName> ToResourceName(const android::ResTable::resource_nam
util::Utf16ToUtf8(StringPiece16(name_in.package, name_in.packageLen));
std::optional<ResourceNamedTypeRef> type;
+ std::string converted;
if (name_in.type) {
- type = ParseResourceNamedType(util::Utf16ToUtf8(StringPiece16(name_in.type, name_in.typeLen)));
+ converted = util::Utf16ToUtf8(StringPiece16(name_in.type, name_in.typeLen));
+ type = ParseResourceNamedType(converted);
} else if (name_in.type8) {
type = ParseResourceNamedType(StringPiece(name_in.type8, name_in.typeLen));
} else {
@@ -85,9 +87,10 @@ std::optional<ResourceName> ToResourceName(const android::AssetManager2::Resourc
name_out.package = std::string(name_in.package, name_in.package_len);
std::optional<ResourceNamedTypeRef> type;
+ std::string converted;
if (name_in.type16) {
- type =
- ParseResourceNamedType(util::Utf16ToUtf8(StringPiece16(name_in.type16, name_in.type_len)));
+ converted = util::Utf16ToUtf8(StringPiece16(name_in.type16, name_in.type_len));
+ type = ParseResourceNamedType(converted);
} else if (name_in.type) {
type = ParseResourceNamedType(StringPiece(name_in.type, name_in.type_len));
} else {
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index d8c76e297ec5..0170c4a4c54b 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -270,6 +270,8 @@ class LinkCommand : public Command {
"Changes the name of the target package for overlay. Most useful\n"
"when used in conjunction with --rename-manifest-package.",
&options_.manifest_fixer_options.rename_overlay_target_package);
+ AddOptionalFlag("--rename-overlay-category", "Changes the category for the overlay.",
+ &options_.manifest_fixer_options.rename_overlay_category);
AddOptionalFlagList("-0", "File suffix not to compress.",
&options_.extensions_to_not_compress);
AddOptionalSwitch("--no-compress", "Do not compress any resources.",
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index d432341a8cde..efa42a2ee1dc 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -449,13 +449,18 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
manifest_action["attribution"]["inherit-from"];
manifest_action["original-package"];
manifest_action["overlay"].Action([&](xml::Element* el) -> bool {
- if (!options_.rename_overlay_target_package) {
- return true;
+ if (options_.rename_overlay_target_package) {
+ if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
+ attr->value = options_.rename_overlay_target_package.value();
+ }
}
-
- if (xml::Attribute* attr =
- el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
- attr->value = options_.rename_overlay_target_package.value();
+ if (options_.rename_overlay_category) {
+ if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "category")) {
+ attr->value = options_.rename_overlay_category.value();
+ } else {
+ el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "category",
+ options_.rename_overlay_category.value()});
+ }
}
return true;
});
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index d5d1d1770e1c..a8707d9d8623 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -48,6 +48,9 @@ struct ManifestFixerOptions {
// <overlay>.
std::optional<std::string> rename_overlay_target_package;
+ // The category to use instead of the one defined in 'android:category' in <overlay>.
+ std::optional<std::string> rename_overlay_category;
+
// The version name to set if 'android:versionName' is not defined in <manifest> or if
// replace_version is set.
std::optional<std::string> version_name_default;
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 432f10bdab97..098d0be7f87d 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -351,6 +351,54 @@ TEST_F(ManifestFixerTest,
EXPECT_THAT(attr->value, StrEq("com.android"));
}
+TEST_F(ManifestFixerTest, AddOverlayCategory) {
+ ManifestFixerOptions options;
+ options.rename_overlay_category = std::string("category");
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <overlay android:targetName="Customization" android:targetPackage="android" />
+ </manifest>)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
+ ASSERT_THAT(overlay_el, NotNull());
+
+ xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("category"));
+}
+
+TEST_F(ManifestFixerTest, OverrideOverlayCategory) {
+ ManifestFixerOptions options;
+ options.rename_overlay_category = std::string("category");
+
+ std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android">
+ <overlay android:targetName="Customization"
+ android:targetPackage="android"
+ android:category="yrogetac"/>
+ </manifest>)EOF",
+ options);
+ ASSERT_THAT(doc, NotNull());
+
+ xml::Element* manifest_el = doc->root.get();
+ ASSERT_THAT(manifest_el, NotNull());
+
+ xml::Element* overlay_el = manifest_el->FindChild({}, "overlay");
+ ASSERT_THAT(overlay_el, NotNull());
+
+ xml::Attribute* attr = overlay_el->FindAttribute(xml::kSchemaAndroid, "category");
+ ASSERT_THAT(attr, NotNull());
+ EXPECT_THAT(attr->value, StrEq("category"));
+}
+
TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
ManifestFixerOptions options;
options.version_name_default = std::string("Beta");
diff --git a/tools/lint/OWNERS b/tools/lint/OWNERS
index 2c526a1e239e..33e237d306fc 100644
--- a/tools/lint/OWNERS
+++ b/tools/lint/OWNERS
@@ -4,3 +4,6 @@ jsharkey@google.com
per-file *CallingSettingsNonUserGetterMethods* = file:/packages/SettingsProvider/OWNERS
per-file *RegisterReceiverFlagDetector* = jacobhobbie@google.com
+# Android lint in the Android platform maintainers
+colefaust@google.com
+farivar@google.com
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt
index 8011b36c9a8f..8f553abfee31 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/EnforcePermissionDetector.kt
@@ -65,8 +65,16 @@ class EnforcePermissionDetector : Detector(), SourceCodeScanner {
if (attr1[i].name != attr2[i].name) {
return false
}
- val v1 = ConstantEvaluator.evaluate(context, attr1[i].value)
- val v2 = ConstantEvaluator.evaluate(context, attr2[i].value)
+ val value1 = attr1[i].value
+ val value2 = attr2[i].value
+ if (value1 == null && value2 == null) {
+ continue
+ }
+ if (value1 == null || value2 == null) {
+ return false
+ }
+ val v1 = ConstantEvaluator.evaluate(context, value1)
+ val v2 = ConstantEvaluator.evaluate(context, value2)
if (v1 != v2) {
return false
}
diff --git a/tools/preload/loadclass/LoadClass.java b/tools/preload/loadclass/LoadClass.java
index a71b6a8b145e..3f6658ab8c65 100644
--- a/tools/preload/loadclass/LoadClass.java
+++ b/tools/preload/loadclass/LoadClass.java
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-import android.util.Log;
import android.os.Debug;
+import android.util.Log;
/**
* Loads a class, runs the garbage collector, and prints showmap output.
@@ -28,7 +28,7 @@ class LoadClass {
System.loadLibrary("android_runtime");
if (registerNatives() < 0) {
- throw new RuntimeException("Error registering natives.");
+ throw new RuntimeException("Error registering natives.");
}
Debug.startAllocCounting();
@@ -46,7 +46,7 @@ class LoadClass {
}
}
- System.gc();
+ Runtime.getRuntime().gc();
int allocCount = Debug.getGlobalAllocCount();
int allocSize = Debug.getGlobalAllocSize();
@@ -73,7 +73,7 @@ class LoadClass {
response.append(',').append(freedCount);
response.append(',').append(freedSize);
response.append(',').append(nativeHeapSize);
-
+
System.out.println(response.toString());
}
diff --git a/tools/processors/staledataclass/Android.bp b/tools/processors/staledataclass/Android.bp
index 1e5097662a0a..2169c49a91a5 100644
--- a/tools/processors/staledataclass/Android.bp
+++ b/tools/processors/staledataclass/Android.bp
@@ -22,17 +22,13 @@ java_plugin {
static_libs: [
"codegen-version-info",
],
- // The --add-modules/exports flags below don't work for kotlinc yet, so pin this module to Java language level 8 (see b/139342589):
- java_version: "1.8",
- openjdk9: {
- javacflags: [
- "--add-modules=jdk.compiler",
- "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
- "--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
- "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
- "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
- ],
- },
+ javacflags: [
+ "--add-modules=jdk.compiler",
+ "--add-exports jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED",
+ "--add-exports jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED",
+ "--add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+ "--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+ ],
use_tools_jar: true,
}
diff --git a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
index 27a8853a2219..1cef5b0c8dfb 100644
--- a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
+++ b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+@file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE")
package android.processor.staledataclass
diff --git a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
index 0fb062f280e3..0b619488c49c 100644
--- a/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
+++ b/tools/sdkparcelables/src/com/android/sdkparcelables/Main.kt
@@ -39,7 +39,7 @@ fun main(args: Array<String>) {
kotlin.system.exitProcess(2)
}
- val ancestorCollector = AncestorCollector(Opcodes.ASM7, null)
+ val ancestorCollector = AncestorCollector(Opcodes.ASM9, null)
for (entry in zipFile.entries()) {
if (entry.name.endsWith(".class")) {
diff --git a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java
index 863f976b8aff..67c5561f348d 100644
--- a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java
+++ b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionClassVisitor.java
@@ -28,7 +28,7 @@ public class TraceInjectionClassVisitor extends ClassVisitor {
private final TraceInjectionConfiguration mParams;
public TraceInjectionClassVisitor(ClassVisitor classVisitor,
TraceInjectionConfiguration params) {
- super(Opcodes.ASM7, classVisitor);
+ super(Opcodes.ASM9, classVisitor);
mParams = params;
}
diff --git a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
index c2bbddcb5668..91e987dc72ee 100644
--- a/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
+++ b/tools/traceinjection/src/com/android/traceinjection/TraceInjectionMethodAdapter.java
@@ -61,7 +61,7 @@ public class TraceInjectionMethodAdapter extends AdviceAdapter {
public TraceInjectionMethodAdapter(MethodVisitor methodVisitor, int access,
String name, String descriptor, TraceInjectionConfiguration params) {
- super(Opcodes.ASM7, methodVisitor, access, name, descriptor);
+ super(Opcodes.ASM9, methodVisitor, access, name, descriptor);
mParams = params;
mIsConstructor = "<init>".equals(name);
}
@@ -157,7 +157,7 @@ public class TraceInjectionMethodAdapter extends AdviceAdapter {
class TracingAnnotationVisitor extends AnnotationVisitor {
TracingAnnotationVisitor(AnnotationVisitor annotationVisitor) {
- super(Opcodes.ASM7, annotationVisitor);
+ super(Opcodes.ASM9, annotationVisitor);
}
@Override