summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java28
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java11
-rw-r--r--core/java/com/android/internal/policy/DecorView.java3
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt19
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt52
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt49
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt22
-rw-r--r--libs/hwui/HardwareBitmapUploader.cpp18
-rw-r--r--libs/hwui/HardwareBitmapUploader.h2
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp9
-rw-r--r--libs/hwui/utils/Color.cpp8
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt5
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt37
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt54
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt274
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt80
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt (renamed from packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt)18
-rw-r--r--packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt117
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt95
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt4
-rw-r--r--ravenwood/Android.bp1
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java35
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java3
-rw-r--r--ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java30
-rw-r--r--ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java20
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java4
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java3
-rw-r--r--ravenwood/runtime-jni/ravenwood_runtime.cpp14
-rw-r--r--services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java5
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java8
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java1
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java2
-rw-r--r--services/tests/appfunctions/Android.bp2
-rw-r--r--services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt131
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java6
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java21
63 files changed, 783 insertions, 690 deletions
diff --git a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
index c4e8b4157752..c4bfae98e33d 100644
--- a/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
+++ b/core/java/android/app/appfunctions/AppFunctionRuntimeMetadata.java
@@ -72,14 +72,32 @@ public class AppFunctionRuntimeMetadata extends GenericDocument {
* we need to have per-package app function schemas.
*
* <p>This schema should be set visible to callers from the package owner itself and for callers
- * with {@link android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
- * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
+ * with {@link android.Manifest.permission#EXECUTE_APP_FUNCTIONS} or {@link
+ * android.Manifest.permission#EXECUTE_APP_FUNCTIONS_TRUSTED} permissions.
*
* @param packageName The package name to create a schema for.
*/
@NonNull
public static AppSearchSchema createAppFunctionRuntimeSchema(@NonNull String packageName) {
- return new AppSearchSchema.Builder(getRuntimeSchemaNameForPackage(packageName))
+ return getAppFunctionRuntimeSchemaBuilder(getRuntimeSchemaNameForPackage(packageName))
+ .addParentType(RUNTIME_SCHEMA_TYPE)
+ .build();
+ }
+
+ /**
+ * Creates a parent schema for all app function runtime schemas.
+ *
+ * <p>This schema should be set visible to the owner itself and for callers with {@link
+ * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
+ * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
+ */
+ public static AppSearchSchema createParentAppFunctionRuntimeSchema() {
+ return getAppFunctionRuntimeSchemaBuilder(RUNTIME_SCHEMA_TYPE).build();
+ }
+
+ private static AppSearchSchema.Builder getAppFunctionRuntimeSchemaBuilder(
+ @NonNull String schemaType) {
+ return new AppSearchSchema.Builder(schemaType)
.addProperty(
new AppSearchSchema.StringPropertyConfig.Builder(PROPERTY_FUNCTION_ID)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
@@ -111,9 +129,7 @@ public class AppFunctionRuntimeMetadata extends GenericDocument {
.setJoinableValueType(
AppSearchSchema.StringPropertyConfig
.JOINABLE_VALUE_TYPE_QUALIFIED_ID)
- .build())
- .addParentType(RUNTIME_SCHEMA_TYPE)
- .build();
+ .build());
}
/** Returns the function id. This might look like "com.example.message#send_message". */
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index cdac09796137..1709ca78af4b 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -404,6 +404,17 @@ public class RuntimeInit {
}
public static void redirectLogStreams$ravenwood() {
+ if (sOut$ravenwood != null && sErr$ravenwood != null) {
+ return; // Already initialized.
+ }
+
+ // Make sure the Log class is loaded and the JNI methods are hooked up,
+ // before redirecting System.out/err.
+ // Otherwise, because ClassLoadHook tries to write to System.out, this would cause
+ // a circular initialization problem and would cause a UnsatisfiedLinkError
+ // on the JNI methods.
+ Log.isLoggable("X", Log.VERBOSE);
+
if (sOut$ravenwood == null) {
sOut$ravenwood = System.out;
System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 58818f35de22..4708be8108c2 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1144,7 +1144,8 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
mDrawLegacyNavigationBarBackground =
((requestedVisibleTypes | mLastForceConsumingTypes)
& WindowInsets.Type.navigationBars()) != 0
- && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0;
+ && (mWindow.getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+ && navBarSize > 0;
if (oldDrawLegacy != mDrawLegacyNavigationBarBackground) {
mDrawLegacyNavigationBarBackgroundHandled =
mWindow.onDrawLegacyNavigationBarBackgroundChanged(
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index ec1d4f7854fd..7640cb1fb616 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -195,6 +195,25 @@ class DesktopModeFlickerScenarios {
.associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
)
+ val CORNER_RESIZE_TO_MAXIMUM_SIZE =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("CORNER_RESIZE_TO_MAXIMUM_SIZE"),
+ extractor =
+ TaggedScenarioExtractorBuilder()
+ .setTargetTag(CujType.CUJ_DESKTOP_MODE_RESIZE_WINDOW)
+ .setTransitionMatcher(
+ TaggedCujTransitionMatcher(associatedTransitionRequired = false)
+ )
+ .build(),
+ assertions =
+ AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
+ listOf(
+ AppLayerIncreasesInSize(DESKTOP_MODE_APP),
+ AppWindowHasMaxDisplayHeight(DESKTOP_MODE_APP),
+ AppWindowHasMaxDisplayWidth(DESKTOP_MODE_APP)
+ ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ )
+
val SNAP_RESIZE_LEFT_WITH_BUTTON =
FlickerConfigEntry(
scenarioId = ScenarioId("SNAP_RESIZE_LEFT_WITH_BUTTON"),
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt
new file mode 100644
index 000000000000..0b98ba2a9cd4
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizeLandscape.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE_TO_MAXIMUM_SIZE
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Resize app window using corner resize to the greatest possible height and width in
+ * landscape mode.
+ *
+ * Assert that the maximum window size constraint is maintained.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppToMaximumWindowSizeLandscape : ResizeAppWithCornerResize(
+ rotation = Rotation.ROTATION_90
+) {
+ @ExpectedScenarios(["CORNER_RESIZE_TO_MAXIMUM_SIZE"])
+ @Test
+ override fun resizeAppWithCornerResizeToMaximumSize() =
+ super.resizeAppWithCornerResizeToMaximumSize()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE_TO_MAXIMUM_SIZE)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt
new file mode 100644
index 000000000000..b1c04d38a46c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/ResizeAppToMaximumWindowSizePortrait.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.flicker
+
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.DesktopModeFlickerScenarios.Companion.CORNER_RESIZE_TO_MAXIMUM_SIZE
+import com.android.wm.shell.scenarios.ResizeAppWithCornerResize
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Resize app window using corner resize to the greatest possible height and width in
+ * portrait mode.
+ *
+ * Assert that the maximum window size constraint is maintained.
+ */
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class ResizeAppToMaximumWindowSizePortrait : ResizeAppWithCornerResize() {
+ @ExpectedScenarios(["CORNER_RESIZE_TO_MAXIMUM_SIZE"])
+ @Test
+ override fun resizeAppWithCornerResizeToMaximumSize() =
+ super.resizeAppWithCornerResizeToMaximumSize()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(CORNER_RESIZE_TO_MAXIMUM_SIZE)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
index d8e131e8de1d..bd25639466a3 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/scenarios/src/com/android/wm/shell/scenarios/ResizeAppWithCornerResize.kt
@@ -36,8 +36,7 @@ import org.junit.Rule
import org.junit.Test
@Ignore("Test Base Class")
-abstract class ResizeAppWithCornerResize
-constructor(
+abstract class ResizeAppWithCornerResize(
val rotation: Rotation = Rotation.ROTATION_0,
val horizontalChange: Int = 200,
val verticalChange: Int = -200,
@@ -79,6 +78,25 @@ constructor(
)
}
+ @Test
+ open fun resizeAppWithCornerResizeToMaximumSize() {
+ val maxResizeChange = 3000
+ testApp.cornerResize(
+ wmHelper,
+ device,
+ DesktopModeAppHelper.Corners.RIGHT_TOP,
+ maxResizeChange,
+ -maxResizeChange
+ )
+ testApp.cornerResize(
+ wmHelper,
+ device,
+ DesktopModeAppHelper.Corners.LEFT_BOTTOM,
+ -maxResizeChange,
+ maxResizeChange
+ )
+ }
+
@After
fun teardown() {
testApp.exit(wmHelper)
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index a2748b050a2d..236c3736816e 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -318,6 +318,11 @@ bool HardwareBitmapUploader::has1010102Support() {
return has101012Support;
}
+bool HardwareBitmapUploader::has10101010Support() {
+ static bool has1010110Support = checkSupport(AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM);
+ return has1010110Support;
+}
+
bool HardwareBitmapUploader::hasAlpha8Support() {
static bool hasAlpha8Support = checkSupport(AHARDWAREBUFFER_FORMAT_R8_UNORM);
return hasAlpha8Support;
@@ -376,6 +381,19 @@ static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
}
formatInfo.format = GL_RGBA;
break;
+ case kRGBA_10x6_SkColorType:
+ formatInfo.isSupported = HardwareBitmapUploader::has10101010Support();
+ if (formatInfo.isSupported) {
+ formatInfo.type = 0; // Not supported in GL
+ formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
+ formatInfo.vkFormat = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16;
+ } else {
+ formatInfo.type = GL_UNSIGNED_BYTE;
+ formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
+ }
+ formatInfo.format = 0; // Not supported in GL
+ break;
case kAlpha_8_SkColorType:
formatInfo.isSupported = HardwareBitmapUploader::hasAlpha8Support();
if (formatInfo.isSupported) {
diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h
index 00ee99648889..76cb80b722d0 100644
--- a/libs/hwui/HardwareBitmapUploader.h
+++ b/libs/hwui/HardwareBitmapUploader.h
@@ -33,12 +33,14 @@ public:
#ifdef __ANDROID__
static bool hasFP16Support();
static bool has1010102Support();
+ static bool has10101010Support();
static bool hasAlpha8Support();
#else
static bool hasFP16Support() {
return true;
}
static bool has1010102Support() { return true; }
+ static bool has10101010Support() { return true; }
static bool hasAlpha8Support() { return true; }
#endif
};
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index bce84ae77c87..e3023937964e 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -318,6 +318,15 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions,
tailPNext = &deviceFaultFeatures->pNext;
}
+ if (grExtensions.hasExtension(VK_EXT_RGBA10X6_FORMATS_EXTENSION_NAME, 1)) {
+ VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT* formatFeatures =
+ new VkPhysicalDeviceRGBA10X6FormatsFeaturesEXT;
+ formatFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RGBA10X6_FORMATS_FEATURES_EXT;
+ formatFeatures->pNext = nullptr;
+ *tailPNext = formatFeatures;
+ tailPNext = &formatFeatures->pNext;
+ }
+
// query to get the physical device features
mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
// this looks like it would slow things down,
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 6a560b365247..9673c5f03642 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -49,6 +49,10 @@ static inline SkImageInfo createImageInfo(int32_t width, int32_t height, int32_t
colorType = kRGBA_1010102_SkColorType;
alphaType = kPremul_SkAlphaType;
break;
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
+ colorType = kRGBA_10x6_SkColorType;
+ alphaType = kPremul_SkAlphaType;
+ break;
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
colorType = kRGBA_F16_SkColorType;
alphaType = kPremul_SkAlphaType;
@@ -86,6 +90,8 @@ uint32_t ColorTypeToBufferFormat(SkColorType colorType) {
return AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
case kRGBA_1010102_SkColorType:
return AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+ case kRGBA_10x6_SkColorType:
+ return AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM;
case kARGB_4444_SkColorType:
// Hardcoding the value from android::PixelFormat
static constexpr uint64_t kRGBA4444 = 7;
@@ -108,6 +114,8 @@ SkColorType BufferFormatToColorType(uint32_t format) {
return kRGB_565_SkColorType;
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
return kRGBA_1010102_SkColorType;
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
+ return kRGBA_10x6_SkColorType;
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
return kRGBA_F16_SkColorType;
case AHARDWAREBUFFER_FORMAT_R8_UNORM:
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
index ecb3d8cb04be..c25a45dc5cf6 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt
@@ -52,6 +52,7 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.res.R
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -97,6 +98,7 @@ fun AlternateBouncer(
Box {
DeviceEntryIcon(
viewModel = alternateBouncerDependencies.udfpsIconViewModel,
+ logger = alternateBouncerDependencies.logger,
modifier =
Modifier.width { udfpsLocation.width }
.height { udfpsLocation.height }
@@ -151,13 +153,14 @@ private fun StatusMessage(
@Composable
private fun DeviceEntryIcon(
viewModel: AlternateBouncerUdfpsIconViewModel,
+ logger: LongPressHandlingViewLogger,
modifier: Modifier = Modifier,
) {
AndroidView(
modifier = modifier,
factory = { context ->
val view =
- DeviceEntryIconView(context, null).apply {
+ DeviceEntryIconView(context, null, logger = logger).apply {
id = R.id.alternate_bouncer_udfps_icon_view
contentDescription =
context.resources.getString(R.string.accessibility_fingerprint_label)
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
index 46cd58ce6dd0..a525f36c71ce 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/LockSection.kt
@@ -44,6 +44,9 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.VibratorHelper
@@ -64,6 +67,7 @@ constructor(
private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
private val falsingManager: Lazy<FalsingManager>,
private val vibratorHelper: Lazy<VibratorHelper>,
+ @LongPressTouchLog private val logBuffer: LogBuffer,
) {
@Composable
fun SceneScope.LockIcon(overrideColor: Color? = null, modifier: Modifier = Modifier) {
@@ -77,19 +81,24 @@ constructor(
factory = { context ->
val view =
if (DeviceEntryUdfpsRefactor.isEnabled) {
- DeviceEntryIconView(context, null).apply {
- id = R.id.device_entry_icon_view
- DeviceEntryIconViewBinder.bind(
- applicationScope,
- this,
- deviceEntryIconViewModel.get(),
- deviceEntryForegroundViewModel.get(),
- deviceEntryBackgroundViewModel.get(),
- falsingManager.get(),
- vibratorHelper.get(),
- overrideColor,
+ DeviceEntryIconView(
+ context,
+ null,
+ logger = LongPressHandlingViewLogger(logBuffer, tag = TAG)
)
- }
+ .apply {
+ id = R.id.device_entry_icon_view
+ DeviceEntryIconViewBinder.bind(
+ applicationScope,
+ this,
+ deviceEntryIconViewModel.get(),
+ deviceEntryForegroundViewModel.get(),
+ deviceEntryBackgroundViewModel.get(),
+ falsingManager.get(),
+ vibratorHelper.get(),
+ overrideColor,
+ )
+ }
} else {
// KeyguardBottomAreaRefactor.isEnabled
LockIconView(context, null).apply {
@@ -178,6 +187,10 @@ constructor(
return IntRect(center, radius)
}
+
+ companion object {
+ private const val TAG = "LockSection"
+ }
}
private val LockIconElementKey = ElementKey("LockIcon")
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index df101c558dff..3cb0d8af1ba4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -128,11 +128,7 @@ fun SceneContainer(
}
},
) {
- SceneTransitionLayout(
- state = state,
- modifier = modifier.fillMaxSize(),
- swipeSourceDetector = viewModel.edgeDetector,
- ) {
+ SceneTransitionLayout(state = state, modifier = modifier.fillMaxSize()) {
sceneByKey.forEach { (sceneKey, scene) ->
scene(
key = sceneKey,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
index 65236f02b635..e3b5f34c8e5a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
@@ -31,6 +31,8 @@ import com.android.systemui.common.ui.data.repository.fakeConfigurationRepositor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
@@ -91,6 +93,8 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() {
kosmos.fakeTelephonyRepository.setHasTelephonyRadio(true)
kosmos.telecomManager = telecomManager
+
+ kosmos.sceneInteractor.changeScene(Scenes.Bouncer, "")
}
@Test
@@ -130,6 +134,7 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() {
assertThat(metricsLogger.logs.element().category)
.isEqualTo(MetricsProto.MetricsEvent.ACTION_EMERGENCY_CALL)
verify(activityTaskManager).stopSystemLockTaskMode()
+ assertThat(kosmos.sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
verify(telecomManager).showInCallScreen(eq(false))
}
@@ -156,6 +161,7 @@ class BouncerActionButtonInteractorTest : SysuiTestCase() {
assertThat(metricsLogger.logs.element().category)
.isEqualTo(MetricsProto.MetricsEvent.ACTION_EMERGENCY_CALL)
verify(activityTaskManager).stopSystemLockTaskMode()
+ assertThat(kosmos.sceneInteractor.currentScene.value).isEqualTo(Scenes.Lockscreen)
// TODO(b/25189994): Test the activity has been started once we switch to the
// ActivityStarter interface here.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
index bb400f274fbe..f06cd6aec8e0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandlerTest.kt
@@ -67,7 +67,8 @@ class LongPressHandlingViewInteractionHandlerTest : SysuiTestCase() {
isAttachedToWindow = { isAttachedToWindow },
onLongPressDetected = onLongPressDetected,
onSingleTapDetected = onSingleTapDetected,
- longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() }
+ longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() },
+ allowedTouchSlop = ViewConfiguration.getTouchSlop(),
)
underTest.isLongPressHandlingEnabled = true
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index a0bb01797f2c..4b132c4276ea 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -18,12 +18,9 @@
package com.android.systemui.scene.ui.viewmodel
-import android.platform.test.annotations.DisableFlags
-import android.platform.test.annotations.EnableFlags
import android.view.MotionEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.compose.animation.scene.DefaultEdgeDetector
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.domain.interactor.falsingInteractor
import com.android.systemui.classifier.fakeFalsingManager
@@ -40,10 +37,6 @@ import com.android.systemui.scene.shared.logger.sceneLogger
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
-import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.flag.DualShade
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -67,7 +60,6 @@ class SceneContainerViewModelTest : SysuiTestCase() {
private val testScope by lazy { kosmos.testScope }
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
- private val fakeShadeRepository by lazy { kosmos.fakeShadeRepository }
private val sceneContainerConfig by lazy { kosmos.sceneContainerConfig }
private val falsingManager by lazy { kosmos.fakeFalsingManager }
@@ -83,8 +75,6 @@ class SceneContainerViewModelTest : SysuiTestCase() {
sceneInteractor = sceneInteractor,
falsingInteractor = kosmos.falsingInteractor,
powerInteractor = kosmos.powerInteractor,
- shadeInteractor = kosmos.shadeInteractor,
- splitEdgeDetector = kosmos.splitEdgeDetector,
logger = kosmos.sceneLogger,
motionEventHandlerReceiver = { motionEventHandler ->
this@SceneContainerViewModelTest.motionEventHandler = motionEventHandler
@@ -297,48 +287,4 @@ class SceneContainerViewModelTest : SysuiTestCase() {
assertThat(actionableContentKey).isEqualTo(Overlays.QuickSettingsShade)
}
-
- @Test
- @DisableFlags(DualShade.FLAG_NAME)
- fun edgeDetector_singleShade_usesDefaultEdgeDetector() =
- testScope.runTest {
- val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(false)
- assertThat(shadeMode).isEqualTo(ShadeMode.Single)
-
- assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
- }
-
- @Test
- @DisableFlags(DualShade.FLAG_NAME)
- fun edgeDetector_splitShade_usesDefaultEdgeDetector() =
- testScope.runTest {
- val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(true)
- assertThat(shadeMode).isEqualTo(ShadeMode.Split)
-
- assertThat(underTest.edgeDetector).isEqualTo(DefaultEdgeDetector)
- }
-
- @Test
- @EnableFlags(DualShade.FLAG_NAME)
- fun edgeDetector_dualShade_narrowScreen_usesSplitEdgeDetector() =
- testScope.runTest {
- val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(false)
-
- assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
- assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
- }
-
- @Test
- @EnableFlags(DualShade.FLAG_NAME)
- fun edgeDetector_dualShade_wideScreen_usesSplitEdgeDetector() =
- testScope.runTest {
- val shadeMode by collectLastValue(kosmos.shadeInteractor.shadeMode)
- fakeShadeRepository.setShadeLayoutWide(true)
-
- assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
- assertThat(underTest.edgeDetector).isEqualTo(kosmos.splitEdgeDetector)
- }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt
deleted file mode 100644
index 3afaa0a235fc..000000000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorTest.kt
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.ui.viewmodel
-
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.dp
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Bottom
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.End
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Left
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Right
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.Start
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopEnd
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopLeft
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopRight
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge.TopStart
-import com.google.common.truth.Truth.assertThat
-import kotlin.test.assertFailsWith
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SplitEdgeDetectorTest : SysuiTestCase() {
-
- private val edgeSize = 40
- private val screenWidth = 800
- private val screenHeight = 600
-
- private var edgeSplitFraction = 0.7f
-
- private val underTest =
- SplitEdgeDetector(
- topEdgeSplitFraction = { edgeSplitFraction },
- edgeSize = edgeSize.dp,
- )
-
- @Test
- fun source_noEdge_detectsNothing() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = screenWidth / 2,
- y = screenHeight / 2,
- )
- assertThat(detectedEdge).isNull()
- }
-
- @Test
- fun source_swipeVerticallyOnTopLeft_detectsTopLeft() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = 1,
- y = edgeSize - 1,
- )
- assertThat(detectedEdge).isEqualTo(TopLeft)
- }
-
- @Test
- fun source_swipeHorizontallyOnTopLeft_detectsLeft() {
- val detectedEdge =
- swipeHorizontallyFrom(
- x = 1,
- y = edgeSize - 1,
- )
- assertThat(detectedEdge).isEqualTo(Left)
- }
-
- @Test
- fun source_swipeVerticallyOnTopRight_detectsTopRight() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = screenWidth - 1,
- y = edgeSize - 1,
- )
- assertThat(detectedEdge).isEqualTo(TopRight)
- }
-
- @Test
- fun source_swipeHorizontallyOnTopRight_detectsRight() {
- val detectedEdge =
- swipeHorizontallyFrom(
- x = screenWidth - 1,
- y = edgeSize - 1,
- )
- assertThat(detectedEdge).isEqualTo(Right)
- }
-
- @Test
- fun source_swipeVerticallyToLeftOfSplit_detectsTopLeft() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = (screenWidth * edgeSplitFraction).toInt() - 1,
- y = edgeSize - 1,
- )
- assertThat(detectedEdge).isEqualTo(TopLeft)
- }
-
- @Test
- fun source_swipeVerticallyToRightOfSplit_detectsTopRight() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = (screenWidth * edgeSplitFraction).toInt() + 1,
- y = edgeSize - 1,
- )
- assertThat(detectedEdge).isEqualTo(TopRight)
- }
-
- @Test
- fun source_edgeSplitFractionUpdatesDynamically() {
- val middleX = (screenWidth * 0.5f).toInt()
- val topY = 0
-
- // Split closer to the right; middle of screen is considered "left".
- edgeSplitFraction = 0.6f
- assertThat(swipeVerticallyFrom(x = middleX, y = topY)).isEqualTo(TopLeft)
-
- // Split closer to the left; middle of screen is considered "right".
- edgeSplitFraction = 0.4f
- assertThat(swipeVerticallyFrom(x = middleX, y = topY)).isEqualTo(TopRight)
-
- // Illegal fraction.
- edgeSplitFraction = 1.2f
- assertFailsWith<IllegalArgumentException> { swipeVerticallyFrom(x = middleX, y = topY) }
-
- // Illegal fraction.
- edgeSplitFraction = -0.3f
- assertFailsWith<IllegalArgumentException> { swipeVerticallyFrom(x = middleX, y = topY) }
- }
-
- @Test
- fun source_swipeVerticallyOnBottom_detectsBottom() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = screenWidth / 3,
- y = screenHeight - (edgeSize / 2),
- )
- assertThat(detectedEdge).isEqualTo(Bottom)
- }
-
- @Test
- fun source_swipeHorizontallyOnBottom_detectsNothing() {
- val detectedEdge =
- swipeHorizontallyFrom(
- x = screenWidth / 3,
- y = screenHeight - (edgeSize - 1),
- )
- assertThat(detectedEdge).isNull()
- }
-
- @Test
- fun source_swipeHorizontallyOnLeft_detectsLeft() {
- val detectedEdge =
- swipeHorizontallyFrom(
- x = edgeSize - 1,
- y = screenHeight / 2,
- )
- assertThat(detectedEdge).isEqualTo(Left)
- }
-
- @Test
- fun source_swipeVerticallyOnLeft_detectsNothing() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = edgeSize - 1,
- y = screenHeight / 2,
- )
- assertThat(detectedEdge).isNull()
- }
-
- @Test
- fun source_swipeHorizontallyOnRight_detectsRight() {
- val detectedEdge =
- swipeHorizontallyFrom(
- x = screenWidth - edgeSize + 1,
- y = screenHeight / 2,
- )
- assertThat(detectedEdge).isEqualTo(Right)
- }
-
- @Test
- fun source_swipeVerticallyOnRight_detectsNothing() {
- val detectedEdge =
- swipeVerticallyFrom(
- x = screenWidth - edgeSize + 1,
- y = screenHeight / 2,
- )
- assertThat(detectedEdge).isNull()
- }
-
- @Test
- fun resolve_startInLtr_resolvesLeft() {
- val resolvedEdge = Start.resolve(LayoutDirection.Ltr)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.Left)
- }
-
- @Test
- fun resolve_startInRtl_resolvesRight() {
- val resolvedEdge = Start.resolve(LayoutDirection.Rtl)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.Right)
- }
-
- @Test
- fun resolve_endInLtr_resolvesRight() {
- val resolvedEdge = End.resolve(LayoutDirection.Ltr)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.Right)
- }
-
- @Test
- fun resolve_endInRtl_resolvesLeft() {
- val resolvedEdge = End.resolve(LayoutDirection.Rtl)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.Left)
- }
-
- @Test
- fun resolve_topStartInLtr_resolvesTopLeft() {
- val resolvedEdge = TopStart.resolve(LayoutDirection.Ltr)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.TopLeft)
- }
-
- @Test
- fun resolve_topStartInRtl_resolvesTopRight() {
- val resolvedEdge = TopStart.resolve(LayoutDirection.Rtl)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.TopRight)
- }
-
- @Test
- fun resolve_topEndInLtr_resolvesTopRight() {
- val resolvedEdge = TopEnd.resolve(LayoutDirection.Ltr)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.TopRight)
- }
-
- @Test
- fun resolve_topEndInRtl_resolvesTopLeft() {
- val resolvedEdge = TopEnd.resolve(LayoutDirection.Rtl)
- assertThat(resolvedEdge).isEqualTo(SceneContainerEdge.Resolved.TopLeft)
- }
-
- private fun swipeVerticallyFrom(x: Int, y: Int): SceneContainerEdge? {
- return swipeFrom(x, y, Orientation.Vertical)
- }
-
- private fun swipeHorizontallyFrom(x: Int, y: Int): SceneContainerEdge? {
- return swipeFrom(x, y, Orientation.Horizontal)
- }
-
- private fun swipeFrom(x: Int, y: Int, orientation: Orientation): SceneContainerEdge? {
- return underTest.source(
- layoutSize = IntSize(width = screenWidth, height = screenHeight),
- position = IntOffset(x, y),
- density = Density(1f),
- orientation = orientation,
- )
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
index 9464c75eeb71..3283ea154b3f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
@@ -24,6 +24,7 @@ import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -38,7 +39,6 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
-import com.android.systemui.shade.data.repository.fakeShadeRepository
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.shade.shared.flag.DualShade
@@ -66,18 +66,18 @@ import platform.test.runner.parameterized.Parameters
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
class ShadeInteractorImplTest(flags: FlagsParameterization) : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
- private val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
- private val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
- private val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
- private val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
- private val powerRepository by lazy { kosmos.fakePowerRepository }
- private val shadeRepository by lazy { kosmos.fakeShadeRepository }
- private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
- private val userRepository by lazy { kosmos.fakeUserRepository }
- private val userSetupRepository by lazy { kosmos.fakeUserSetupRepository }
- private val dozeParameters by lazy { kosmos.dozeParameters }
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+ val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
+ val deviceProvisioningRepository by lazy { kosmos.fakeDeviceProvisioningRepository }
+ val disableFlagsRepository by lazy { kosmos.fakeDisableFlagsRepository }
+ val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+ val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
+ val powerRepository by lazy { kosmos.fakePowerRepository }
+ val shadeTestUtil by lazy { kosmos.shadeTestUtil }
+ val userRepository by lazy { kosmos.fakeUserRepository }
+ val userSetupRepository by lazy { kosmos.fakeUserSetupRepository }
+ val dozeParameters by lazy { kosmos.dozeParameters }
lateinit var underTest: ShadeInteractorImpl
@@ -497,24 +497,4 @@ class ShadeInteractorImplTest(flags: FlagsParameterization) : SysuiTestCase() {
assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
}
-
- @Test
- fun getTopEdgeSplitFraction_narrowScreen_splitInHalf() =
- testScope.runTest {
- // Ensure isShadeLayoutWide is collected.
- val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
- shadeRepository.setShadeLayoutWide(false)
-
- assertThat(underTest.getTopEdgeSplitFraction()).isEqualTo(0.5f)
- }
-
- @Test
- fun getTopEdgeSplitFraction_wideScreen_leftSideLarger() =
- testScope.runTest {
- // Ensure isShadeLayoutWide is collected.
- val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
- shadeRepository.setShadeLayoutWide(true)
-
- assertThat(underTest.getTopEdgeSplitFraction()).isGreaterThan(0.5f)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
index f36ef6630a48..8b5a09b3d9fd 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractor.kt
@@ -34,10 +34,14 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.doze.DozeLogger
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.EmergencyDialerConstants
+import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
@@ -69,6 +73,7 @@ constructor(
private val emergencyDialerIntentFactory: EmergencyDialerIntentFactory,
private val metricsLogger: MetricsLogger,
private val dozeLogger: DozeLogger,
+ private val sceneInteractor: Lazy<SceneInteractor>,
) {
/** The bouncer action button. If `null`, the button should not be shown. */
val actionButton: Flow<BouncerActionButtonModel?> =
@@ -158,14 +163,17 @@ constructor(
}
private fun prepareToPerformAction() {
- // TODO(b/308001302): Trigger occlusion and resetting bouncer state.
+ if (SceneContainerFlag.isEnabled) {
+ sceneInteractor.get().changeScene(Scenes.Lockscreen, "Bouncer action button clicked")
+ }
+
metricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL)
activityTaskManager.stopSystemLockTaskMode()
}
@SuppressLint("MissingPermission")
private fun returnToCall() {
- telecomManager?.showInCallScreen(/* showDialpad = */ false)
+ telecomManager?.showInCallScreen(/* showDialpad= */ false)
}
private val <T> Flow<T>.asUnitFlow: Flow<Unit>
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
index b6ace81d18ba..9c4736a13b46 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingView.kt
@@ -27,6 +27,7 @@ import android.view.ViewConfiguration
import android.view.accessibility.AccessibilityNodeInfo
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.shade.TouchLogger
import kotlin.math.pow
import kotlin.math.sqrt
@@ -42,6 +43,8 @@ class LongPressHandlingView(
context: Context,
attrs: AttributeSet?,
longPressDuration: () -> Long,
+ allowedTouchSlop: Int = ViewConfiguration.getTouchSlop(),
+ logger: LongPressHandlingViewLogger? = null,
) :
View(
context,
@@ -97,6 +100,8 @@ class LongPressHandlingView(
},
onSingleTapDetected = { listener?.onSingleTapDetected(this@LongPressHandlingView) },
longPressDuration = longPressDuration,
+ allowedTouchSlop = allowedTouchSlop,
+ logger = logger,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
index d3fc610bc52e..4e38a4913fe6 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LongPressHandlingViewInteractionHandler.kt
@@ -17,7 +17,7 @@
package com.android.systemui.common.ui.view
-import android.view.ViewConfiguration
+import com.android.systemui.log.LongPressHandlingViewLogger
import kotlinx.coroutines.DisposableHandle
/** Encapsulates logic to handle complex touch interactions with a [LongPressHandlingView]. */
@@ -35,6 +35,14 @@ class LongPressHandlingViewInteractionHandler(
private val onSingleTapDetected: () -> Unit,
/** Time for the touch to be considered a long-press in ms */
var longPressDuration: () -> Long,
+ /**
+ * Default touch slop that is allowed, if the movement between [MotionEventModel.Down] and
+ * [MotionEventModel.Up] is more than [allowedTouchSlop] then the touch is not processed as
+ * single tap or a long press.
+ */
+ val allowedTouchSlop: Int,
+ /** Optional logger that can be passed in to log touch events */
+ val logger: LongPressHandlingViewLogger? = null,
) {
sealed class MotionEventModel {
object Other : MotionEventModel()
@@ -70,22 +78,26 @@ class LongPressHandlingViewInteractionHandler(
true
}
is MotionEventModel.Move -> {
- if (event.distanceMoved > ViewConfiguration.getTouchSlop()) {
+ if (event.distanceMoved > allowedTouchSlop) {
+ logger?.cancelingLongPressDueToTouchSlop(event.distanceMoved, allowedTouchSlop)
cancelScheduledLongPress()
}
false
}
is MotionEventModel.Up -> {
+ logger?.onUpEvent(event.distanceMoved, allowedTouchSlop, event.gestureDuration)
cancelScheduledLongPress()
if (
- event.distanceMoved <= ViewConfiguration.getTouchSlop() &&
+ event.distanceMoved <= allowedTouchSlop &&
event.gestureDuration < longPressDuration()
) {
+ logger?.dispatchingSingleTap()
dispatchSingleTap()
}
false
}
is MotionEventModel.Cancel -> {
+ logger?.motionEventCancelled()
cancelScheduledLongPress()
false
}
@@ -97,15 +109,18 @@ class LongPressHandlingViewInteractionHandler(
x: Int,
y: Int,
) {
+ val duration = longPressDuration()
+ logger?.schedulingLongPress(duration)
scheduledLongPressHandle =
postDelayed(
{
+ logger?.longPressTriggered()
dispatchLongPress(
x = x,
y = y,
)
},
- longPressDuration(),
+ duration,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
index 91a7f7fc66bd..76962732ad01 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -42,6 +42,7 @@ import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerWindowViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scrim.ScrimView
@@ -191,6 +192,7 @@ constructor(
optionallyAddUdfpsViews(
view = view,
+ logger = alternateBouncerDependencies.logger,
udfpsIconViewModel = alternateBouncerDependencies.udfpsIconViewModel,
udfpsA11yOverlayViewModel =
alternateBouncerDependencies.udfpsAccessibilityOverlayViewModel,
@@ -248,6 +250,7 @@ constructor(
private fun optionallyAddUdfpsViews(
view: ConstraintLayout,
+ logger: LongPressHandlingViewLogger,
udfpsIconViewModel: AlternateBouncerUdfpsIconViewModel,
udfpsA11yOverlayViewModel: Lazy<AlternateBouncerUdfpsAccessibilityOverlayViewModel>,
) {
@@ -276,7 +279,7 @@ constructor(
var udfpsView = view.getViewById(udfpsViewId)
if (udfpsView == null) {
udfpsView =
- DeviceEntryIconView(view.context, null).apply {
+ DeviceEntryIconView(view.context, null, logger = logger).apply {
id = udfpsViewId
contentDescription =
context.resources.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
index 4d6577c0423a..b951b736abf2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/DeviceEntryIconViewBinder.kt
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.ui.binder
import android.annotation.SuppressLint
import android.content.res.ColorStateList
+import android.util.Log
import android.util.StateSet
import android.view.HapticFeedbackConstants
import android.view.View
@@ -83,6 +84,11 @@ object DeviceEntryIconViewBinder {
if (
!isA11yAction && falsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)
) {
+ Log.d(
+ TAG,
+ "Long press rejected because it is not a11yAction " +
+ "and it is a falseLongTap"
+ )
return
}
vibratorHelper.performHapticFeedback(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
index 3e6d5da38257..8d2e939da032 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/DeviceEntryIconView.kt
@@ -23,6 +23,7 @@ import android.util.AttributeSet
import android.util.StateSet
import android.view.Gravity
import android.view.View
+import android.view.ViewConfiguration
import android.view.ViewGroup
import android.view.accessibility.AccessibilityNodeInfo
import android.widget.FrameLayout
@@ -31,6 +32,7 @@ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
import com.airbnb.lottie.LottieCompositionFactory
import com.airbnb.lottie.LottieDrawable
import com.android.systemui.common.ui.view.LongPressHandlingView
+import com.android.systemui.log.LongPressHandlingViewLogger
import com.android.systemui.res.R
class DeviceEntryIconView
@@ -39,8 +41,17 @@ constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttrs: Int = 0,
+ logger: LongPressHandlingViewLogger? = null,
) : FrameLayout(context, attrs, defStyleAttrs) {
- val longPressHandlingView: LongPressHandlingView = LongPressHandlingView(context, attrs)
+
+ val longPressHandlingView: LongPressHandlingView =
+ LongPressHandlingView(
+ context = context,
+ attrs = attrs,
+ longPressDuration = { ViewConfiguration.getLongPressTimeout().toLong() },
+ allowedTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(),
+ logger = logger,
+ )
val iconView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_fg }
val bgView: ImageView = ImageView(context, attrs).apply { id = R.id.device_entry_icon_bg }
val aodFpDrawable: LottieDrawable = LottieDrawable()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
index 51230dd0a47c..782d37b1929c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySection.kt
@@ -42,6 +42,9 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
@@ -69,6 +72,7 @@ constructor(
private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
private val falsingManager: Lazy<FalsingManager>,
private val vibratorHelper: Lazy<VibratorHelper>,
+ @LongPressTouchLog private val logBuffer: LogBuffer,
) : KeyguardSection() {
private val deviceEntryIconViewId = R.id.device_entry_icon_view
private var disposableHandle: DisposableHandle? = null
@@ -88,7 +92,16 @@ constructor(
val view =
if (DeviceEntryUdfpsRefactor.isEnabled) {
- DeviceEntryIconView(context, null).apply { id = deviceEntryIconViewId }
+ DeviceEntryIconView(
+ context,
+ null,
+ logger =
+ LongPressHandlingViewLogger(
+ logBuffer = logBuffer,
+ TAG
+ )
+ )
+ .apply { id = deviceEntryIconViewId }
} else {
// KeyguardBottomAreaRefactor.isEnabled or MigrateClocksToBlueprint.isEnabled
LockIconView(context, null).apply { id = R.id.lock_icon_view }
@@ -258,4 +271,8 @@ constructor(
}
}
}
+
+ companion object {
+ private const val TAG = "DefaultDeviceEntrySection"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
index b432417802c9..9f8e9c575a75 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerDependencies.kt
@@ -18,6 +18,9 @@ package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel
import com.android.systemui.keyguard.ui.SwipeUpAnywhereGestureHandler
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LongPressHandlingViewLogger
+import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.statusbar.gesture.TapGestureDetector
import dagger.Lazy
@@ -37,4 +40,11 @@ constructor(
Lazy<AlternateBouncerUdfpsAccessibilityOverlayViewModel>,
val messageAreaViewModel: AlternateBouncerMessageAreaViewModel,
val powerInteractor: PowerInteractor,
-)
+ @LongPressTouchLog private val touchLogBuffer: LogBuffer,
+) {
+ val logger: LongPressHandlingViewLogger =
+ LongPressHandlingViewLogger(logBuffer = touchLogBuffer, TAG)
+ companion object {
+ private const val TAG = "AlternateBouncer"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt b/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt
new file mode 100644
index 000000000000..4ff81184d045
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LongPressHandlingViewLogger.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import com.android.systemui.log.core.LogLevel.DEBUG
+import com.google.errorprone.annotations.CompileTimeConstant
+
+data class LongPressHandlingViewLogger
+constructor(
+ private val logBuffer: LogBuffer,
+ @CompileTimeConstant private val tag: String = "LongPressHandlingViewLogger"
+) {
+ fun schedulingLongPress(delay: Long) {
+ logBuffer.log(
+ tag,
+ DEBUG,
+ { long1 = delay },
+ { "on MotionEvent.Down: scheduling long press activation after $long1 ms" }
+ )
+ }
+
+ fun longPressTriggered() {
+ logBuffer.log(tag, DEBUG, "long press event detected and dispatched")
+ }
+
+ fun motionEventCancelled() {
+ logBuffer.log(tag, DEBUG, "Long press may be cancelled due to MotionEventModel.Cancel")
+ }
+
+ fun dispatchingSingleTap() {
+ logBuffer.log(tag, DEBUG, "Dispatching single tap instead of long press")
+ }
+
+ fun onUpEvent(distanceMoved: Float, touchSlop: Int, gestureDuration: Long) {
+ logBuffer.log(
+ tag,
+ DEBUG,
+ {
+ double1 = distanceMoved.toDouble()
+ int1 = touchSlop
+ long1 = gestureDuration
+ },
+ {
+ "on MotionEvent.Up: distanceMoved: $double1, " +
+ "allowedTouchSlop: $int1, " +
+ "eventDuration: $long1"
+ }
+ )
+ }
+
+ fun cancelingLongPressDueToTouchSlop(distanceMoved: Float, allowedTouchSlop: Int) {
+ logBuffer.log(
+ tag,
+ DEBUG,
+ {
+ double1 = distanceMoved.toDouble()
+ int1 = allowedTouchSlop
+ },
+ {
+ "on MotionEvent.Motion: May cancel long press due to movement: " +
+ "distanceMoved: $double1, " +
+ "allowedTouchSlop: $int1 "
+ }
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 19906fdc4d5f..498c34c03f2d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -717,4 +717,12 @@ public class LogModule {
public static LogBuffer provideVolumeLogBuffer(LogBufferFactory factory) {
return factory.create("VolumeLog", 50);
}
+
+ /** Provides a {@link LogBuffer} for use by long touch event handlers. */
+ @Provides
+ @SysUISingleton
+ @LongPressTouchLog
+ public static LogBuffer providesLongPressTouchLog(LogBufferFactory factory) {
+ return factory.create("LongPressViewLog", 200);
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt
index e0b529261c4d..1163d74b62a9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetectorKosmos.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LongPressTouchLog.kt
@@ -14,16 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.scene.ui.viewmodel
+package com.android.systemui.log.dagger
-import androidx.compose.ui.unit.dp
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.shade.domain.interactor.shadeInteractor
+import javax.inject.Qualifier
-var Kosmos.splitEdgeDetector: SplitEdgeDetector by
- Kosmos.Fixture {
- SplitEdgeDetector(
- topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
- edgeSize = 40.dp,
- )
- }
+/** Log buffer for logging touch/long press events */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class LongPressTouchLog
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
index 11854d9317c9..a5c07bc2fdbf 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
@@ -18,13 +18,9 @@ package com.android.systemui.notifications.ui.viewmodel
import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.Swipe
-import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
-import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
-import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -38,10 +34,8 @@ class NotificationsShadeUserActionsViewModel @AssistedInject constructor() :
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
setActions(
mapOf(
- Back to SceneFamilies.Home,
Swipe.Up to SceneFamilies.Home,
- Swipe(direction = SwipeDirection.Down, fromSource = SceneContainerEdge.TopRight) to
- ReplaceByOverlay(Overlays.QuickSettingsShade),
+ Back to SceneFamilies.Home,
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
index bd1872d455d0..d3dc302d44ca 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
@@ -18,13 +18,9 @@ package com.android.systemui.qs.ui.viewmodel
import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.Swipe
-import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
-import com.android.compose.animation.scene.UserActionResult.ReplaceByOverlay
-import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneContainerEdge
import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -47,13 +43,6 @@ constructor(
.map { editing ->
buildMap {
put(Swipe.Up, UserActionResult(SceneFamilies.Home))
- put(
- Swipe(
- direction = SwipeDirection.Down,
- fromSource = SceneContainerEdge.TopLeft
- ),
- ReplaceByOverlay(Overlays.NotificationsShade)
- )
if (!editing) {
put(Back, UserActionResult(SceneFamilies.Home))
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 834db98263f5..00944b8d0849 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -16,7 +16,6 @@
package com.android.systemui.scene
-import androidx.compose.ui.unit.dp
import com.android.systemui.CoreStartable
import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
import com.android.systemui.scene.domain.SceneDomainModule
@@ -31,8 +30,6 @@ import com.android.systemui.scene.domain.startable.StatusBarStartable
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.SplitEdgeDetector
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.flag.DualShade
import dagger.Binds
import dagger.Module
@@ -122,15 +119,5 @@ interface KeyguardlessSceneContainerFrameworkModule {
.mapValues { checkNotNull(it.value) }
)
}
-
- @Provides
- fun splitEdgeDetector(shadeInteractor: ShadeInteractor): SplitEdgeDetector {
- return SplitEdgeDetector(
- topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
- // TODO(b/338577208): This should be 60dp at the top in the dual-shade UI. Better to
- // replace this constant with dynamic window insets.
- edgeSize = 40.dp
- )
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index a4c7d00d0e80..4061ad851f57 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -16,7 +16,6 @@
package com.android.systemui.scene
-import androidx.compose.ui.unit.dp
import com.android.systemui.CoreStartable
import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
import com.android.systemui.scene.domain.SceneDomainModule
@@ -31,8 +30,6 @@ import com.android.systemui.scene.domain.startable.StatusBarStartable
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.SplitEdgeDetector
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.flag.DualShade
import dagger.Binds
import dagger.Module
@@ -132,15 +129,5 @@ interface SceneContainerFrameworkModule {
.mapValues { checkNotNull(it.value) }
)
}
-
- @Provides
- fun splitEdgeDetector(shadeInteractor: ShadeInteractor): SplitEdgeDetector {
- return SplitEdgeDetector(
- topEdgeSplitFraction = shadeInteractor::getTopEdgeSplitFraction,
- // TODO(b/338577208): This should be 60dp at the top in the dual-shade UI. Better to
- // replace this constant with dynamic window insets.
- edgeSize = 40.dp
- )
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index 54823945a827..4c6341b672ad 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -19,11 +19,9 @@ package com.android.systemui.scene.ui.viewmodel
import android.view.MotionEvent
import androidx.compose.runtime.getValue
import com.android.compose.animation.scene.ContentKey
-import com.android.compose.animation.scene.DefaultEdgeDetector
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
-import com.android.compose.animation.scene.SwipeSourceDetector
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.classifier.Classifier
@@ -35,15 +33,12 @@ import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Overlay
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.map
/** Models UI state for the scene container. */
class SceneContainerViewModel
@@ -52,8 +47,6 @@ constructor(
private val sceneInteractor: SceneInteractor,
private val falsingInteractor: FalsingInteractor,
private val powerInteractor: PowerInteractor,
- private val shadeInteractor: ShadeInteractor,
- private val splitEdgeDetector: SplitEdgeDetector,
private val logger: SceneLogger,
@Assisted private val motionEventHandlerReceiver: (MotionEventHandler?) -> Unit,
) : ExclusiveActivatable() {
@@ -66,20 +59,6 @@ constructor(
/** Whether the container is visible. */
val isVisible: Boolean by hydrator.hydratedStateOf("isVisible", sceneInteractor.isVisible)
- /**
- * The [SwipeSourceDetector] to use for defining which edges of the screen can be defined in the
- * [UserAction]s for this container.
- */
- val edgeDetector: SwipeSourceDetector by
- hydrator.hydratedStateOf(
- traceName = "edgeDetector",
- initialValue = DefaultEdgeDetector,
- source =
- shadeInteractor.shadeMode.map {
- if (it is ShadeMode.Dual) splitEdgeDetector else DefaultEdgeDetector
- }
- )
-
override suspend fun onActivated(): Nothing {
try {
// Sends a MotionEventHandler to the owner of the view-model so they can report
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt
deleted file mode 100644
index 59235e24e998..000000000000
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SplitEdgeDetector.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.scene.ui.viewmodel
-
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.IntOffset
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import com.android.compose.animation.scene.Edge
-import com.android.compose.animation.scene.FixedSizeEdgeDetector
-import com.android.compose.animation.scene.SwipeSource
-import com.android.compose.animation.scene.SwipeSourceDetector
-
-/**
- * The edge of a [SceneContainer]. It differs from a standard [Edge] by splitting the top edge into
- * top-left and top-right.
- */
-enum class SceneContainerEdge(private val resolveEdge: (LayoutDirection) -> Resolved) :
- SwipeSource {
- TopLeft(resolveEdge = { Resolved.TopLeft }),
- TopRight(resolveEdge = { Resolved.TopRight }),
- TopStart(
- resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.TopLeft else Resolved.TopRight }
- ),
- TopEnd(
- resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.TopRight else Resolved.TopLeft }
- ),
- Bottom(resolveEdge = { Resolved.Bottom }),
- Left(resolveEdge = { Resolved.Left }),
- Right(resolveEdge = { Resolved.Right }),
- Start(resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.Left else Resolved.Right }),
- End(resolveEdge = { if (it == LayoutDirection.Ltr) Resolved.Right else Resolved.Left });
-
- override fun resolve(layoutDirection: LayoutDirection): Resolved {
- return resolveEdge(layoutDirection)
- }
-
- enum class Resolved : SwipeSource.Resolved {
- TopLeft,
- TopRight,
- Bottom,
- Left,
- Right,
- }
-}
-
-/**
- * A [SwipeSourceDetector] that detects edges similarly to [FixedSizeEdgeDetector], except that the
- * top edge is split in two: top-left and top-right. The split point between the two is dynamic and
- * may change during runtime.
- *
- * Callers who need to detect the start and end edges based on the layout direction (LTR vs RTL)
- * should subscribe to [SceneContainerEdge.TopStart] and [SceneContainerEdge.TopEnd] instead. These
- * will be resolved at runtime to [SceneContainerEdge.Resolved.TopLeft] and
- * [SceneContainerEdge.Resolved.TopRight] appropriately. Similarly, [SceneContainerEdge.Start] and
- * [SceneContainerEdge.End] will be resolved appropriately to [SceneContainerEdge.Resolved.Left] and
- * [SceneContainerEdge.Resolved.Right].
- *
- * @param topEdgeSplitFraction A function which returns the fraction between [0..1] (i.e.,
- * percentage) of screen width to consider the split point between "top-left" and "top-right"
- * edges. It is called on each source detection event.
- * @param edgeSize The fixed size of each edge.
- */
-class SplitEdgeDetector(
- val topEdgeSplitFraction: () -> Float,
- val edgeSize: Dp,
-) : SwipeSourceDetector {
-
- private val fixedEdgeDetector = FixedSizeEdgeDetector(edgeSize)
-
- override fun source(
- layoutSize: IntSize,
- position: IntOffset,
- density: Density,
- orientation: Orientation,
- ): SceneContainerEdge? {
- val fixedEdge =
- fixedEdgeDetector.source(
- layoutSize,
- position,
- density,
- orientation,
- )
- return when (fixedEdge) {
- Edge.Top -> {
- val topEdgeSplitFraction = topEdgeSplitFraction()
- require(topEdgeSplitFraction in 0f..1f) {
- "topEdgeSplitFraction must return a value between 0.0 and 1.0"
- }
- val isLeftSide = position.x < layoutSize.width * topEdgeSplitFraction
- if (isLeftSide) SceneContainerEdge.TopLeft else SceneContainerEdge.TopRight
- }
- Edge.Left -> SceneContainerEdge.Left
- Edge.Bottom -> SceneContainerEdge.Bottom
- Edge.Right -> SceneContainerEdge.Right
- Edge.Start -> SceneContainerEdge.Start
- Edge.End -> SceneContainerEdge.End
- null -> null
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index 3cd91be469c1..73e86a2be4aa 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -16,7 +16,6 @@
package com.android.systemui.shade.domain.interactor
-import androidx.annotation.FloatRange
import com.android.systemui.shade.shared.model.ShadeMode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -70,20 +69,6 @@ interface ShadeInteractor : BaseShadeInteractor {
* wide as the entire screen.
*/
val isShadeLayoutWide: StateFlow<Boolean>
-
- /**
- * The fraction between [0..1] (i.e., percentage) of screen width to consider the threshold
- * between "top-left" and "top-right" for the purposes of dual-shade invocation.
- *
- * When the dual-shade is not wide, this always returns 0.5 (the top edge is evenly split). On
- * wide layouts however, a larger fraction is returned because only the area of the system
- * status icons is considered top-right.
- *
- * Note that this fraction only determines the split between the absolute left and right
- * directions. In RTL layouts, the "top-start" edge will resolve to "top-right", and "top-end"
- * will resolve to "top-left".
- */
- @FloatRange(from = 0.0, to = 1.0) fun getTopEdgeSplitFraction(): Float
}
/** ShadeInteractor methods with implementations that differ between non-empty impls. */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
index 6c0b55a5dd57..d51fd28d5458 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
@@ -47,6 +47,4 @@ class ShadeInteractorEmptyImpl @Inject constructor() : ShadeInteractor {
override val isExpandToQsEnabled: Flow<Boolean> = inactiveFlowBoolean
override val shadeMode: StateFlow<ShadeMode> = MutableStateFlow(ShadeMode.Single)
override val isShadeLayoutWide: StateFlow<Boolean> = inactiveFlowBoolean
-
- override fun getTopEdgeSplitFraction(): Float = 0.5f
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
index b8d2dd2a764f..3552092d24e7 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
@@ -16,7 +16,6 @@
package com.android.systemui.shade.domain.interactor
-import androidx.annotation.FloatRange
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardRepository
@@ -105,16 +104,6 @@ constructor(
override val isShadeLayoutWide: StateFlow<Boolean> = shadeRepository.isShadeLayoutWide
- @FloatRange(from = 0.0, to = 1.0)
- override fun getTopEdgeSplitFraction(): Float {
- // Note: this implicitly relies on isShadeLayoutWide being hot (i.e. collected). This
- // assumption allows us to query its value on demand (during swipe source detection) instead
- // of running another infinite coroutine.
- // TODO(b/338577208): Instead of being fixed at 0.8f, this should dynamically updated based
- // on the position of system-status icons in the status bar.
- return if (shadeRepository.isShadeLayoutWide.value) 0.8f else 0.5f
- }
-
override val shadeMode: StateFlow<ShadeMode> =
isShadeLayoutWide
.map(this::determineShadeMode)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
index 85bbe7e53493..d6013192f55e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/model/NetworkNameModel.kt
@@ -100,7 +100,14 @@ fun Intent.toNetworkNameModel(separator: String): NetworkNameModel? {
val showSpn = getBooleanExtra(EXTRA_SHOW_SPN, false)
val spn =
if (statusBarSwitchToSpnFromDataSpn()) {
- getStringExtra(EXTRA_SPN)
+ // Context: b/358669494. Use DATA_SPN if it exists, since that allows carriers to
+ // customize the display name. Otherwise, fall back to the SPN
+ val dataSpn = getStringExtra(EXTRA_DATA_SPN)
+ if (dataSpn.isNullOrEmpty()) {
+ getStringExtra(EXTRA_SPN)
+ } else {
+ dataSpn
+ }
} else {
getStringExtra(EXTRA_DATA_SPN)
}
@@ -109,10 +116,8 @@ fun Intent.toNetworkNameModel(separator: String): NetworkNameModel? {
val plmn = getStringExtra(EXTRA_PLMN)
val str = StringBuilder()
- val strData = StringBuilder()
if (showPlmn && plmn != null) {
str.append(plmn)
- strData.append(plmn)
}
if (showSpn && spn != null) {
if (str.isNotEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
index 4b0e5d188ffa..6d99183dec33 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt
@@ -29,11 +29,12 @@ import kotlinx.coroutines.flow.StateFlow
class TelephonyInteractor
@Inject
constructor(
- repository: TelephonyRepository,
+ private val repository: TelephonyRepository,
) {
@Annotation.CallState val callState: Flow<Int> = repository.callState
val isInCall: StateFlow<Boolean> = repository.isInCall
- val hasTelephonyRadio: Boolean = repository.hasTelephonyRadio
+ val hasTelephonyRadio: Boolean
+ get() = repository.hasTelephonyRadio
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
index 7cc91853a749..bfb8a57e6271 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultDeviceEntrySectionTest.kt
@@ -34,6 +34,7 @@ import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryIconViewModel
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.shade.NotificationPanelView
@@ -86,6 +87,7 @@ class DefaultDeviceEntrySectionTest : SysuiTestCase() {
{ mock(DeviceEntryBackgroundViewModel::class.java) },
{ falsingManager },
{ mock(VibratorHelper::class.java) },
+ logcatLogBuffer(),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index fe408e3246c8..763449028f28 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -817,7 +817,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
captor.lastValue.onReceive(context, intent)
// spnIntent() sets all values to true and test strings
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
job.cancel()
}
@@ -852,7 +852,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
verify(context).registerReceiver(captor.capture(), any())
captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
// WHEN an intent with a different subId is sent
val wrongSubIntent = spnIntent(subId = 101)
@@ -860,7 +860,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
captor.lastValue.onReceive(context, wrongSubIntent)
// THEN the previous intent's name is still used
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
job.cancel()
}
@@ -902,7 +902,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
verify(context).registerReceiver(captor.capture(), any())
captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
val intentWithoutInfo =
spnIntent(
@@ -961,7 +961,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
// The value is still there despite no active subscribers
assertThat(underTest.networkName.value)
- .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
+ .isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
}
@Test
@@ -986,7 +986,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
@Test
@EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
- fun networkName_allFieldsSet_doesNotUseDataSpn() =
+ fun networkName_allFieldsSet_prioritizesDataSpnOverSpn() =
testScope.runTest {
val latest by collectLastValue(underTest.networkName)
val captor = argumentCaptor<BroadcastReceiver>()
@@ -1002,6 +1002,27 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
plmn = PLMN,
)
captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_spnAndPlmn_fallbackToSpnWhenNullDataSpn() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = SPN,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = PLMN,
+ )
+ captor.lastValue.onReceive(context, intent)
assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
}
@@ -1043,7 +1064,27 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
plmn = PLMN,
)
captor.lastValue.onReceive(context, intent)
- assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN"))
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$DATA_SPN"))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_showPlmn_plmnNotNull_showSpn_spnNotNull_dataSpnNull() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = SPN,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = PLMN,
+ )
+ captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$PLMN$SEP$SPN"))
}
@Test
@@ -1102,10 +1143,50 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
plmn = null,
)
captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$DATA_SPN"))
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_showPlmn_plmnNull_showSpn_dataSpnNull() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = SPN,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = null,
+ )
+ captor.lastValue.onReceive(context, intent)
assertThat(latest).isEqualTo(NetworkNameModel.IntentDerived("$SPN"))
}
@Test
+ @EnableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
+ fun networkName_showPlmn_plmnNull_showSpn_bothSpnNull() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.networkName)
+ val captor = argumentCaptor<BroadcastReceiver>()
+ verify(context).registerReceiver(captor.capture(), any())
+ val intent =
+ spnIntent(
+ subId = SUB_1_ID,
+ showSpn = true,
+ spn = null,
+ dataSpn = null,
+ showPlmn = true,
+ plmn = null,
+ )
+ captor.lastValue.onReceive(context, intent)
+ assertThat(latest).isEqualTo(DEFAULT_NAME_MODEL)
+ }
+
+ @Test
@DisableFlags(Flags.FLAG_STATUS_BAR_SWITCH_TO_SPN_FROM_DATA_SPN)
fun networkName_showPlmn_plmnNull_showSpn_flagOff() =
testScope.runTest {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
index 5ced578ad974..3087d01a2479 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorKosmos.kt
@@ -26,6 +26,7 @@ import com.android.systemui.bouncer.data.repository.emergencyServicesRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.repository.mobileConnectionsRepository
import com.android.systemui.telephony.domain.interactor.telephonyInteractor
import com.android.systemui.user.domain.interactor.selectedUserInteractor
@@ -50,5 +51,6 @@ val Kosmos.bouncerActionButtonInteractor by Fixture {
},
metricsLogger = metricsLogger,
dozeLogger = mock(),
+ sceneInteractor = { sceneInteractor },
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
index 1e95fc12bdb5..740d8919cbc0 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
@@ -34,6 +34,7 @@ import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerViewModel
import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerWindowViewModel
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.statusbar.gesture.TapGestureDetector
import com.android.systemui.util.mockito.mock
@@ -64,6 +65,7 @@ private val Kosmos.alternateBouncerDependencies by
},
messageAreaViewModel = mock<AlternateBouncerMessageAreaViewModel>(),
powerInteractor = powerInteractor,
+ touchLogBuffer = logcatLogBuffer(),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index 874463819c73..55f3ed7062aa 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -12,8 +12,6 @@ import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.FakeOverlay
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
-import com.android.systemui.scene.ui.viewmodel.splitEdgeDetector
-import com.android.systemui.shade.domain.interactor.shadeInteractor
import kotlinx.coroutines.flow.MutableStateFlow
var Kosmos.sceneKeys by Fixture {
@@ -72,8 +70,6 @@ val Kosmos.sceneContainerViewModel by Fixture {
sceneInteractor = sceneInteractor,
falsingInteractor = falsingInteractor,
powerInteractor = powerInteractor,
- shadeInteractor = shadeInteractor,
- splitEdgeDetector = splitEdgeDetector,
motionEventHandlerReceiver = {},
logger = sceneLogger
)
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 9b0c8e554d64..333fe4c8147f 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -127,6 +127,7 @@ java_library {
libs: [
"framework-minus-apex.ravenwood",
"ravenwood-junit",
+ "ravenwood-helper-libcore-runtime",
],
visibility: ["//visibility:private"],
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
index f237ba908507..1d182da5e7fd 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunnerHook.java
@@ -27,6 +27,9 @@ import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.internal.os.RuntimeInit;
+import com.android.ravenwood.common.RavenwoodCommonUtils;
+
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runners.model.TestClass;
@@ -35,7 +38,7 @@ import org.junit.runners.model.TestClass;
* Provide hook points created by {@link RavenwoodAwareTestRunner}.
*/
public class RavenwoodAwareTestRunnerHook {
- private static final String TAG = "RavenwoodAwareTestRunnerHook";
+ private static final String TAG = RavenwoodAwareTestRunner.TAG;
private RavenwoodAwareTestRunnerHook() {
}
@@ -56,20 +59,36 @@ public class RavenwoodAwareTestRunnerHook {
* Called when a runner starts, before the inner runner gets a chance to run.
*/
public static void onRunnerInitializing(Runner runner, TestClass testClass) {
+ // TODO: Move the initialization code to a better place.
+
+ initOnce();
+
// This log call also ensures the framework JNI is loaded.
Log.i(TAG, "onRunnerInitializing: testClass=" + testClass.getJavaClass()
+ " runner=" + runner);
- // TODO: Move the initialization code to a better place.
+ // This is needed to make AndroidJUnit4ClassRunner happy.
+ InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
+ }
+
+ private static boolean sInitialized = false;
+
+ private static void initOnce() {
+ if (sInitialized) {
+ return;
+ }
+ sInitialized = true;
+
+ // We haven't initialized liblog yet, so directly write to System.out here.
+ RavenwoodCommonUtils.log(TAG, "initOnce()");
+
+ // Redirect stdout/stdin to liblog.
+ RuntimeInit.redirectLogStreams();
// This will let AndroidJUnit4 use the original runner.
System.setProperty("android.junit.runner",
"androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner");
System.setProperty(RAVENWOOD_VERSION_JAVA_SYSPROP, "1");
-
-
- // This is needed to make AndroidJUnit4ClassRunner happy.
- InstrumentationRegistry.registerInstance(null, Bundle.EMPTY);
}
/**
@@ -87,7 +106,7 @@ public class RavenwoodAwareTestRunnerHook {
*/
public static boolean onBefore(RavenwoodAwareTestRunner runner, Description description,
Scope scope, Order order) {
- Log.i(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
+ Log.v(TAG, "onBefore: description=" + description + ", " + scope + ", " + order);
if (scope == Scope.Class && order == Order.First) {
// Keep track of the current class.
@@ -113,7 +132,7 @@ public class RavenwoodAwareTestRunnerHook {
*/
public static boolean onAfter(RavenwoodAwareTestRunner runner, Description description,
Scope scope, Order order, Throwable th) {
- Log.i(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
+ Log.v(TAG, "onAfter: description=" + description + ", " + scope + ", " + order + ", " + th);
if (scope == Scope.Instance && order == Order.First) {
getStats().onTestFinished(sCurrentClassDescription, description,
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
index a2088fd0b77f..0059360a0a29 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuleImpl.java
@@ -36,7 +36,6 @@ import android.view.DisplayAdjustments;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.internal.os.RuntimeInit;
import com.android.server.LocalServices;
import org.junit.runner.Description;
@@ -92,8 +91,6 @@ public class RavenwoodRuleImpl {
Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler);
}
- RuntimeInit.redirectLogStreams();
-
android.os.Process.init$ravenwood(rule.mUid, rule.mPid);
android.os.Binder.init$ravenwood();
setSystemProperties(rule.mSystemProperties);
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
index 7d991663f4b1..bfde9cb7099e 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java
@@ -23,7 +23,6 @@ import static java.lang.annotation.ElementType.TYPE;
import android.util.Log;
-import com.android.ravenwood.common.RavenwoodCommonUtils;
import com.android.ravenwood.common.SneakyThrow;
import org.junit.Assume;
@@ -75,7 +74,7 @@ import java.lang.reflect.InvocationTargetException;
* (no hooks, etc.)
*/
public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orderable {
- private static final String TAG = "RavenwoodAwareTestRunner";
+ public static final String TAG = "Ravenwood";
@Inherited
@Target({TYPE})
@@ -142,16 +141,9 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
private Description mDescription = null;
private Throwable mExceptionInConstructor = null;
- /** Simple logging method. */
- private void log(String message) {
- RavenwoodCommonUtils.log(TAG, "[" + getTestClass().getJavaClass() + " @" + this + "] "
- + message);
- }
-
- private Error logAndFail(String message, Throwable innerException) {
- log(message);
- log(" Exception=" + innerException);
- throw new AssertionError(message, innerException);
+ private Error logAndFail(String message, Throwable exception) {
+ Log.e(TAG, message, exception);
+ throw new AssertionError(message, exception);
}
public TestClass getTestClass() {
@@ -165,6 +157,8 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
try {
mTestClass = new TestClass(testClass);
+ onRunnerInitializing();
+
/*
* If the class has @DisabledOnRavenwood, then we'll delegate to
* ClassSkippingTestRunner, which simply skips it.
@@ -186,10 +180,8 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
realRunnerClass = BlockJUnit4ClassRunner.class;
}
- onRunnerInitializing();
-
try {
- log("Initializing the inner runner: " + realRunnerClass);
+ Log.i(TAG, "Initializing the inner runner: " + realRunnerClass);
mRealRunner = instantiateRealRunner(realRunnerClass, testClass);
mDescription = mRealRunner.getDescription();
@@ -201,8 +193,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
} catch (Throwable th) {
// If we throw in the constructor, Tradefed may not report it and just ignore the class,
// so record it and throw it when the test actually started.
- log("Fatal: Exception detected in constructor: " + th.getMessage() + "\n"
- + Log.getStackTraceString(th));
+ Log.e(TAG, "Fatal: Exception detected in constructor", th);
mExceptionInConstructor = new RuntimeException("Exception detected in constructor",
th);
mDescription = Description.createTestDescription(testClass, "Constructor");
@@ -236,8 +227,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
if (!isOnRavenwood()) {
return;
}
-
- log("onRunnerInitializing");
+ // DO NOT USE android.util.Log before calling onRunnerInitializing().
RavenwoodAwareTestRunnerHook.onRunnerInitializing(this, mTestClass);
@@ -250,7 +240,7 @@ public class RavenwoodAwareTestRunner extends Runner implements Filterable, Orde
if (!isOnRavenwood()) {
return;
}
- log("runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
+ Log.v(TAG, "runAnnotatedMethodsOnRavenwood() " + annotationClass.getName());
for (var method : getTestClass().getAnnotatedMethods(annotationClass)) {
ensureIsPublicVoidMethod(method.getMethod(), /* isStatic=*/ instance == null);
diff --git a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
index 0f955e772445..c519204d0586 100644
--- a/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
+++ b/ravenwood/runtime-helper-src/framework/com/android/platform/test/ravenwood/runtimehelper/ClassLoadHook.java
@@ -15,6 +15,9 @@
*/
package com.android.platform.test.ravenwood.runtimehelper;
+import android.system.ErrnoException;
+import android.system.Os;
+
import com.android.ravenwood.common.RavenwoodCommonUtils;
import java.io.File;
@@ -37,6 +40,14 @@ public class ClassLoadHook {
private static final boolean SKIP_LOADING_LIBANDROID = "1".equals(System.getenv(
"RAVENWOOD_SKIP_LOADING_LIBANDROID"));
+ /**
+ * If set to 1, and if $ANDROID_LOG_TAGS isn't set, we enable the verbose logging.
+ *
+ * (See also InitLogging() in http://ac/system/libbase/logging.cpp)
+ */
+ private static final boolean RAVENWOOD_VERBOSE_LOGGING = "1".equals(System.getenv(
+ "RAVENWOOD_VERBOSE"));
+
public static final String CORE_NATIVE_CLASSES = "core_native_classes";
public static final String ICU_DATA_PATH = "icu.data.path";
public static final String KEYBOARD_PATHS = "keyboard_paths";
@@ -123,6 +134,15 @@ public class ClassLoadHook {
return;
}
+ if (RAVENWOOD_VERBOSE_LOGGING) {
+ log("Force enabling verbose logging");
+ try {
+ Os.setenv("ANDROID_LOG_TAGS", "*:v", true);
+ } catch (ErrnoException e) {
+ // Shouldn't happen.
+ }
+ }
+
// Make sure these properties are not set.
ensurePropertyNotSet(CORE_NATIVE_CLASSES);
ensurePropertyNotSet(ICU_DATA_PATH);
diff --git a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
index a5c0b54a8637..c94ef31a5e5e 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/android/system/Os.java
@@ -93,4 +93,8 @@ public final class Os {
throw new ErrnoException("pread", OsConstants.EIO, e);
}
}
+
+ public static void setenv(String name, String value, boolean overwrite) throws ErrnoException {
+ RavenwoodRuntimeNative.setenv(name, value, overwrite);
+ }
}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
index 0d8408c12033..ad80d92686ab 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/com/android/ravenwood/RavenwoodRuntimeNative.java
@@ -53,6 +53,9 @@ public class RavenwoodRuntimeNative {
private static native int nOpen(String path, int flags, int mode) throws ErrnoException;
+ public static native void setenv(String name, String value, boolean overwrite)
+ throws ErrnoException;
+
public static long lseek(FileDescriptor fd, long offset, int whence) throws ErrnoException {
return nLseek(JvmWorkaround.getInstance().getFdInt(fd), offset, whence);
}
diff --git a/ravenwood/runtime-jni/ravenwood_runtime.cpp b/ravenwood/runtime-jni/ravenwood_runtime.cpp
index f5cb019f4e7e..c255be5f61aa 100644
--- a/ravenwood/runtime-jni/ravenwood_runtime.cpp
+++ b/ravenwood/runtime-jni/ravenwood_runtime.cpp
@@ -214,6 +214,19 @@ static jint Linux_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint
return throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
}
+static void Linux_setenv(JNIEnv* env, jobject, jstring javaName, jstring javaValue,
+ jboolean overwrite) {
+ ScopedRealUtf8Chars name(env, javaName);
+ if (name.c_str() == NULL) {
+ jniThrowNullPointerException(env);
+ }
+ ScopedRealUtf8Chars value(env, javaValue);
+ if (value.c_str() == NULL) {
+ jniThrowNullPointerException(env);
+ }
+ throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite ? 1 : 0));
+}
+
// ---- Registration ----
static const JNINativeMethod sMethods[] =
@@ -227,6 +240,7 @@ static const JNINativeMethod sMethods[] =
{ "lstat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_lstat },
{ "stat", "(Ljava/lang/String;)Landroid/system/StructStat;", (void*)Linux_stat },
{ "nOpen", "(Ljava/lang/String;II)I", (void*)Linux_open },
+ { "setenv", "(Ljava/lang/String;Ljava/lang/String;Z)V", (void*)Linux_setenv },
};
extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
diff --git a/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java b/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java
index 6effeb3058d9..eba628dc1fba 100644
--- a/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java
+++ b/services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java
@@ -25,7 +25,6 @@ import android.app.appsearch.AppSearchManager;
import android.app.appsearch.AppSearchManager.SearchContext;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSession;
-import android.app.appsearch.BatchResultCallback;
import android.app.appsearch.GetSchemaResponse;
import android.app.appsearch.PutDocumentsRequest;
import android.app.appsearch.SearchResult;
@@ -50,7 +49,6 @@ import java.util.concurrent.Executor;
public class FutureAppSearchSession implements Closeable {
private static final String TAG = FutureAppSearchSession.class.getSimpleName();
private final Executor mExecutor;
- private final AppSearchManager mAppSearchManager;
private final AndroidFuture<AppSearchResult<AppSearchSession>> mSettableSessionFuture;
public FutureAppSearchSession(
@@ -62,9 +60,8 @@ public class FutureAppSearchSession implements Closeable {
Objects.requireNonNull(appSearchContext);
mExecutor = executor;
- mAppSearchManager = appSearchManager;
mSettableSessionFuture = new AndroidFuture<>();
- mAppSearchManager.createSearchSession(
+ appSearchManager.createSearchSession(
appSearchContext, mExecutor, mSettableSessionFuture::complete);
}
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 907e7c639352..86015acc232f 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -938,7 +938,7 @@ public class AutomaticBrightnessController {
setAmbientLux(mFastAmbientLux);
if (mLoggingEnabled) {
Slog.d(TAG, "updateAmbientLux: "
- + ((mFastAmbientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
+ + ((mFastAmbientLux > mPreThresholdLux) ? "Brightened" : "Darkened") + ": "
+ "mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold + ", "
+ "mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold + ", "
+ "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", "
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index bed012bddf90..ed16b1472ee5 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1276,6 +1276,9 @@ public final class DisplayManagerService extends SystemService {
|| isUidPresentOnDisplayInternal(callingUid, displayId)) {
return info;
}
+ } else if (displayId == Display.DEFAULT_DISPLAY) {
+ Slog.e(TAG, "Default display is null for info request from uid "
+ + callingUid);
}
return null;
}
@@ -2224,10 +2227,11 @@ public final class DisplayManagerService extends SystemService {
if (display.isValidLocked()) {
applyDisplayChangedLocked(display);
}
- return;
+ } else {
+ releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
}
- releaseDisplayAndEmitEvent(display, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
+ Slog.i(TAG, "Logical display removed: " + display.getDisplayIdLocked());
}
private void releaseDisplayAndEmitEvent(LogicalDisplay display, int event) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bb2bed7281f7..7c591e3a2c03 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -2222,6 +2222,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
unblockScreenOn();
}
mWindowManagerPolicy.screenTurningOn(mDisplayId, mPendingScreenOnUnblocker);
+ Slog.i(TAG, "Window Manager Policy screenTurningOn complete");
}
// Return true if the screen isn't blocked.
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 12e7fd010e3d..71cb8820761f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3668,7 +3668,7 @@ public final class PowerManagerService extends SystemService
mBrightWhenDozingConfig);
int wakefulness = powerGroup.getWakefulnessLocked();
if (DEBUG_SPEW) {
- Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready
+ Slog.d(TAG, "updatePowerGroupsLocked: displayReady=" + ready
+ ", groupId=" + groupId
+ ", policy=" + policyToString(powerGroup.getPolicyLocked())
+ ", mWakefulness="
diff --git a/services/tests/appfunctions/Android.bp b/services/tests/appfunctions/Android.bp
index e681fa8fec29..b5cf98697d54 100644
--- a/services/tests/appfunctions/Android.bp
+++ b/services/tests/appfunctions/Android.bp
@@ -37,7 +37,7 @@ android_test {
"androidx.test.runner",
"androidx.test.ext.truth",
"platform-test-annotations",
- "services.core",
+ "services.appfunctions",
"servicestests-core-utils",
"truth",
"frameworks-base-testutils",
diff --git a/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt
new file mode 100644
index 000000000000..5233f194d6c5
--- /dev/null
+++ b/services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.appfunctions
+
+import android.app.appfunctions.AppFunctionRuntimeMetadata
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema
+import android.app.appfunctions.AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema
+import android.app.appsearch.AppSearchManager
+import android.app.appsearch.PutDocumentsRequest
+import android.app.appsearch.SearchSpec
+import android.app.appsearch.SetSchemaRequest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class FutureAppSearchSessionTest {
+ private val context = InstrumentationRegistry.getInstrumentation().targetContext
+ private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
+ private val testExecutor = MoreExecutors.directExecutor()
+
+ @Before
+ @After
+ fun clearData() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
+ val setSchemaRequest = SetSchemaRequest.Builder().build()
+ it.setSchema(setSchemaRequest)
+ }
+ }
+
+ @Test
+ fun setSchema() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+ )
+ .build()
+
+ val schema = session.setSchema(setSchemaRequest)
+
+ assertThat(schema.get()).isNotNull()
+ }
+ }
+
+ @Test
+ fun put() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+ )
+ .build()
+ val schema = session.setSchema(setSchemaRequest)
+ assertThat(schema.get()).isNotNull()
+ val appFunctionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder()
+ .addGenericDocuments(appFunctionRuntimeMetadata)
+ .build()
+
+ val putResult = session.put(putDocumentsRequest)
+
+ assertThat(putResult.get().isSuccess).isTrue()
+ }
+ }
+
+ @Test
+ fun search() {
+ val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
+ FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
+ val setSchemaRequest =
+ SetSchemaRequest.Builder()
+ .addSchemas(
+ createParentAppFunctionRuntimeSchema(),
+ createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
+ )
+ .build()
+ val schema = session.setSchema(setSchemaRequest)
+ assertThat(schema.get()).isNotNull()
+ val appFunctionRuntimeMetadata =
+ AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
+ val putDocumentsRequest: PutDocumentsRequest =
+ PutDocumentsRequest.Builder()
+ .addGenericDocuments(appFunctionRuntimeMetadata)
+ .build()
+ val putResult = session.put(putDocumentsRequest)
+ assertThat(putResult.get().isSuccess).isTrue()
+
+ val searchResult = session.search("", SearchSpec.Builder().build())
+
+ val genericDocs =
+ searchResult.get().nextPage.get().stream().map { it.genericDocument }.toList()
+ assertThat(genericDocs).hasSize(1)
+ val foundAppFunctionRuntimeMetadata = AppFunctionRuntimeMetadata(genericDocs[0])
+ assertThat(foundAppFunctionRuntimeMetadata.functionId).isEqualTo(TEST_FUNCTION_ID)
+ }
+ }
+
+ private companion object {
+ const val TEST_DB: String = "test_db"
+ const val TEST_PACKAGE_NAME: String = "test_pkg"
+ const val TEST_FUNCTION_ID: String = "print"
+ }
+}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f0850af5fc2e..51e0c33ff705 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1456,21 +1456,21 @@ public class SubscriptionManager {
public static final int SERVICE_CAPABILITY_MAX = SERVICE_CAPABILITY_DATA;
/**
- * Bitmask for {@code SERVICE_CAPABILITY_VOICE}.
+ * Bitmask for {@link #SERVICE_CAPABILITY_VOICE}.
* @hide
*/
public static final int SERVICE_CAPABILITY_VOICE_BITMASK =
serviceCapabilityToBitmask(SERVICE_CAPABILITY_VOICE);
/**
- * Bitmask for {@code SERVICE_CAPABILITY_SMS}.
+ * Bitmask for {@link #SERVICE_CAPABILITY_SMS}.
* @hide
*/
public static final int SERVICE_CAPABILITY_SMS_BITMASK =
serviceCapabilityToBitmask(SERVICE_CAPABILITY_SMS);
/**
- * Bitmask for {@code SERVICE_CAPABILITY_DATA}.
+ * Bitmask for {@link #SERVICE_CAPABILITY_DATA}.
* @hide
*/
public static final int SERVICE_CAPABILITY_DATA_BITMASK =
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3ff1e2ca8dfb..3e226ccf2737 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6907,7 +6907,6 @@ public class TelephonyManager {
return false;
}
- // TODO(b/316183370): replace all @code with @link in javadoc after feature is released
/**
* @return true if the current device is "voice capable".
* <p>
@@ -6921,10 +6920,10 @@ public class TelephonyManager {
* PackageManager.FEATURE_TELEPHONY system feature, which is available
* on any device with a telephony radio, even if the device is
* data-only.
- * @deprecated Replaced by {@code #isDeviceVoiceCapable()}. Starting from Android 15, voice
+ * @deprecated Replaced by {@link #isDeviceVoiceCapable()}. Starting from Android 15, voice
* capability may also be overridden by carriers for a given subscription. For voice capable
- * device (when {@code #isDeviceVoiceCapable} return {@code true}), caller should check for
- * subscription-level voice capability as well. See {@code #isDeviceVoiceCapable} for details.
+ * device (when {@link #isDeviceVoiceCapable} return {@code true}), caller should check for
+ * subscription-level voice capability as well. See {@link #isDeviceVoiceCapable} for details.
*/
@Deprecated
public boolean isVoiceCapable() {
@@ -6946,8 +6945,8 @@ public class TelephonyManager {
* <p>
* Starting from Android 15, voice capability may also be overridden by carrier for a given
* subscription on a voice capable device. To check if a subscription is "voice capable",
- * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if
- * {@code SubscriptionManager#SERVICE_CAPABILITY_VOICE} is included.
+ * call method {@link SubscriptionInfo#getServiceCapabilities()} and check if
+ * {@link SubscriptionManager#SERVICE_CAPABILITY_VOICE} is included.
*
* @see SubscriptionInfo#getServiceCapabilities()
*/
@@ -6964,10 +6963,10 @@ public class TelephonyManager {
* <p>
* Note: Voicemail waiting sms, cell broadcasting sms, and MMS are
* disabled when device doesn't support sms.
- * @deprecated Replaced by {@code #isDeviceSmsCapable()}. Starting from Android 15, SMS
+ * @deprecated Replaced by {@link #isDeviceSmsCapable()}. Starting from Android 15, SMS
* capability may also be overridden by carriers for a given subscription. For SMS capable
- * device (when {@code #isDeviceSmsCapable} return {@code true}), caller should check for
- * subscription-level SMS capability as well. See {@code #isDeviceSmsCapable} for details.
+ * device (when {@link #isDeviceSmsCapable} return {@code true}), caller should check for
+ * subscription-level SMS capability as well. See {@link #isDeviceSmsCapable} for details.
*/
@Deprecated
public boolean isSmsCapable() {
@@ -6986,8 +6985,8 @@ public class TelephonyManager {
* <p>
* Starting from Android 15, SMS capability may also be overridden by carriers for a given
* subscription on an SMS capable device. To check if a subscription is "SMS capable",
- * call method {@code SubscriptionInfo#getServiceCapabilities()} and check if
- * {@code SubscriptionManager#SERVICE_CAPABILITY_SMS} is included.
+ * call method {@link SubscriptionInfo#getServiceCapabilities()} and check if
+ * {@link SubscriptionManager#SERVICE_CAPABILITY_SMS} is included.
*
* @see SubscriptionInfo#getServiceCapabilities()
*/