Merge "Cleaning up deprecate_flags_and_settings_resets" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index e5c059e..8b95679 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -230,6 +230,17 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+java_aconfig_library {
+ name: "telephony_flags_core_java_exported_lib",
+ aconfig_declarations: "telephony_flags",
+ mode: "exported",
+ min_sdk_version: "30",
+ apex_available: [
+ "com.android.wifi",
+ ],
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
cc_aconfig_library {
name: "telephony_flags_c_lib",
aconfig_declarations: "telephony_flags",
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f63170a..588ca1d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -387,7 +387,7 @@
@UnsupportedAppUsage
private ContextImpl mSystemContext;
@GuardedBy("this")
- private ArrayList<WeakReference<ContextImpl>> mDisplaySystemUiContexts;
+ private ArrayList<WeakReference<Context>> mDisplaySystemUiContexts;
@UnsupportedAppUsage
static volatile IPackageManager sPackageManager;
@@ -3204,7 +3204,7 @@
}
@NonNull
- public ContextImpl getSystemUiContext() {
+ public Context getSystemUiContext() {
return getSystemUiContext(DEFAULT_DISPLAY);
}
@@ -3214,7 +3214,7 @@
* @see ContextImpl#createSystemUiContext(ContextImpl, int)
*/
@NonNull
- public ContextImpl getSystemUiContext(int displayId) {
+ public Context getSystemUiContext(int displayId) {
synchronized (this) {
if (mDisplaySystemUiContexts == null) {
mDisplaySystemUiContexts = new ArrayList<>();
@@ -3222,7 +3222,7 @@
mDisplaySystemUiContexts.removeIf(contextRef -> contextRef.refersTo(null));
- ContextImpl context = getSystemUiContextNoCreateLocked(displayId);
+ Context context = getSystemUiContextNoCreateLocked(displayId);
if (context != null) {
return context;
}
@@ -3233,9 +3233,20 @@
}
}
+ /**
+ * Creates a {@code SystemUiContext} for testing.
+ * <p>
+ * DO NOT use it in production code.
+ */
+ @VisibleForTesting
+ @NonNull
+ public Context createSystemUiContextForTesting(int displayId) {
+ return ContextImpl.createSystemUiContext(getSystemContext(), displayId);
+ }
+
@Nullable
@Override
- public ContextImpl getSystemUiContextNoCreate() {
+ public Context getSystemUiContextNoCreate() {
synchronized (this) {
if (mDisplaySystemUiContexts == null) {
return null;
@@ -3246,9 +3257,9 @@
@GuardedBy("this")
@Nullable
- private ContextImpl getSystemUiContextNoCreateLocked(int displayId) {
+ private Context getSystemUiContextNoCreateLocked(int displayId) {
for (int i = 0; i < mDisplaySystemUiContexts.size(); i++) {
- ContextImpl context = mDisplaySystemUiContexts.get(i).get();
+ Context context = mDisplaySystemUiContexts.get(i).get();
if (context != null && context.getDisplayId() == displayId) {
return context;
}
@@ -3267,7 +3278,8 @@
public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
synchronized (this) {
getSystemContext().installSystemApplicationInfo(info, classLoader);
- getSystemUiContext().installSystemApplicationInfo(info, classLoader);
+ final ContextImpl sysUiContextImpl = ContextImpl.getImpl(getSystemUiContext());
+ sysUiContextImpl.installSystemApplicationInfo(info, classLoader);
// give ourselves a default profiler
mProfiler = new Profiler();
diff --git a/core/java/android/app/ActivityThreadInternal.java b/core/java/android/app/ActivityThreadInternal.java
index 72506b9..70876da 100644
--- a/core/java/android/app/ActivityThreadInternal.java
+++ b/core/java/android/app/ActivityThreadInternal.java
@@ -17,6 +17,7 @@
package android.app;
import android.content.ComponentCallbacks2;
+import android.content.Context;
import java.util.ArrayList;
@@ -28,7 +29,7 @@
interface ActivityThreadInternal {
ContextImpl getSystemContext();
- ContextImpl getSystemUiContextNoCreate();
+ Context getSystemUiContextNoCreate();
boolean isInDensityCompatMode();
diff --git a/core/java/android/app/ConfigurationController.java b/core/java/android/app/ConfigurationController.java
index 62a50db..f491e3d 100644
--- a/core/java/android/app/ConfigurationController.java
+++ b/core/java/android/app/ConfigurationController.java
@@ -169,7 +169,7 @@
// Get theme outside of synchronization to avoid nested lock.
final Resources.Theme systemTheme = mActivityThread.getSystemContext().getTheme();
- final ContextImpl systemUiContext = mActivityThread.getSystemUiContextNoCreate();
+ final Context systemUiContext = mActivityThread.getSystemUiContextNoCreate();
final Resources.Theme systemUiTheme =
systemUiContext != null ? systemUiContext.getTheme() : null;
synchronized (mResourcesManager) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d8aa8b3..0519695 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -97,6 +97,7 @@
import android.view.Display;
import android.view.DisplayAdjustments;
import android.view.autofill.AutofillManager.AutofillClient;
+import android.window.SystemUiContext;
import android.window.WindowContext;
import android.window.WindowTokenClient;
import android.window.WindowTokenClientController;
@@ -3477,15 +3478,28 @@
* {@link #createSystemContext(ActivityThread)}.
* @param displayId The ID of the display where the UI is shown.
*/
- static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
+ static Context createSystemUiContext(ContextImpl systemContext, int displayId) {
+ // Step 1. Create a ContextImpl associated with its own resources.
final WindowTokenClient token = new WindowTokenClient();
final ContextImpl context = systemContext.createWindowContextBase(token, displayId);
- token.attachContext(context);
+
+ // Step 2. Create a SystemUiContext to wrap the ContextImpl, which enables to listen to
+ // its config updates.
+ final Context systemUiContext;
+ if (com.android.window.flags.Flags.trackSystemUiContextBeforeWms()) {
+ systemUiContext = new SystemUiContext(context);
+ context.setOuterContext(systemUiContext);
+ } else {
+ systemUiContext = context;
+ }
+ token.attachContext(systemUiContext);
+
+ // Step 3. Associate the SystemUiContext with the display specified with ID.
WindowTokenClientController.getInstance().attachToDisplayContent(token, displayId);
context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI;
context.mOwnsToken = true;
- return context;
+ return systemUiContext;
}
@UnsupportedAppUsage
diff --git a/core/java/android/window/DesktopModeFlags.java b/core/java/android/window/DesktopModeFlags.java
index ca1017b..23da747 100644
--- a/core/java/android/window/DesktopModeFlags.java
+++ b/core/java/android/window/DesktopModeFlags.java
@@ -115,6 +115,7 @@
ENABLE_WINDOWING_SCALED_RESIZING(Flags::enableWindowingScaledResizing, true),
ENABLE_WINDOWING_TRANSITION_HANDLERS_OBSERVERS(
Flags::enableWindowingTransitionHandlersObservers, false),
+ EXCLUDE_CAPTION_FROM_APP_BOUNDS(Flags::excludeCaptionFromAppBounds, false),
INCLUDE_TOP_TRANSPARENT_FULLSCREEN_TASK_IN_DESKTOP_HEURISTIC(
Flags::includeTopTransparentFullscreenTaskInDesktopHeuristic, true)
// go/keep-sorted end
diff --git a/core/java/android/window/SystemUiContext.java b/core/java/android/window/SystemUiContext.java
new file mode 100644
index 0000000..1e9a720
--- /dev/null
+++ b/core/java/android/window/SystemUiContext.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.NonNull;
+import android.content.ComponentCallbacks;
+import android.content.ComponentCallbacksController;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.res.Configuration;
+
+import com.android.window.flags.Flags;
+
+/**
+ * System Context to be used for UI. This Context has resources that can be themed.
+ *
+ * @see android.app.ActivityThread#getSystemUiContext(int)
+ *
+ * @hide
+ */
+public class SystemUiContext extends ContextWrapper implements ConfigurationDispatcher {
+
+ private final ComponentCallbacksController mCallbacksController =
+ new ComponentCallbacksController();
+
+ public SystemUiContext(Context base) {
+ super(base);
+ if (!Flags.trackSystemUiContextBeforeWms()) {
+ throw new UnsupportedOperationException("SystemUiContext can only be used after"
+ + " flag is enabled.");
+ }
+ }
+
+ @Override
+ public void registerComponentCallbacks(@NonNull ComponentCallbacks callback) {
+ mCallbacksController.registerCallbacks(callback);
+ }
+
+ @Override
+ public void unregisterComponentCallbacks(@NonNull ComponentCallbacks callback) {
+ mCallbacksController.unregisterCallbacks(callback);
+ }
+
+ /** Dispatch {@link Configuration} to each {@link ComponentCallbacks}. */
+ @Override
+ public void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
+ mCallbacksController.dispatchConfigurationChanged(newConfig);
+ }
+
+ @Override
+ public boolean shouldReportPrivateChanges() {
+ // We should report all config changes to update fields obtained from resources.
+ return true;
+ }
+}
diff --git a/core/java/com/android/internal/app/MediaRouteControllerDialog.java b/core/java/com/android/internal/app/MediaRouteControllerDialog.java
index 61e63d1..621ec50 100644
--- a/core/java/com/android/internal/app/MediaRouteControllerDialog.java
+++ b/core/java/com/android/internal/app/MediaRouteControllerDialog.java
@@ -16,13 +16,10 @@
package com.android.internal.app;
-import com.android.internal.R;
-
import android.app.AlertDialog;
import android.app.MediaRouteActionProvider;
import android.app.MediaRouteButton;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.AnimationDrawable;
@@ -39,6 +36,8 @@
import android.widget.LinearLayout;
import android.widget.SeekBar;
+import com.android.internal.R;
+
/**
* This class implements the route controller dialog for {@link MediaRouter}.
* <p>
@@ -60,7 +59,6 @@
private final MediaRouterCallback mCallback;
private final MediaRouter.RouteInfo mRoute;
- private boolean mCreated;
private Drawable mMediaRouteButtonDrawable;
private int[] mMediaRouteConnectingState = { R.attr.state_checked, R.attr.state_enabled };
private int[] mMediaRouteOnState = { R.attr.state_activated, R.attr.state_enabled };
@@ -102,31 +100,6 @@
}
/**
- * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}.
- *
- * @return The media control view, or null if none.
- */
- public View getMediaControlView() {
- return mControlView;
- }
-
- /**
- * Sets whether to enable the volume slider and volume control using the volume keys
- * when the route supports it.
- * <p>
- * The default value is true.
- * </p>
- */
- public void setVolumeControlEnabled(boolean enable) {
- if (mVolumeControlEnabled != enable) {
- mVolumeControlEnabled = enable;
- if (mCreated) {
- updateVolume();
- }
- }
- }
-
- /**
* Returns whether to enable the volume slider and volume control using the volume keys
* when the route supports it.
*/
@@ -139,18 +112,15 @@
setTitle(mRoute.getName());
Resources res = getContext().getResources();
setButton(BUTTON_NEGATIVE, res.getString(R.string.media_route_controller_disconnect),
- new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int id) {
- if (mRoute.isSelected()) {
- if (mRoute.isBluetooth()) {
- mRouter.getDefaultRoute().select();
- } else {
- mRouter.getFallbackRoute().select();
- }
+ (dialogInterface, id) -> {
+ if (mRoute.isSelected()) {
+ if (mRoute.isBluetooth()) {
+ mRouter.getDefaultRoute().select();
+ } else {
+ mRouter.getFallbackRoute().select();
}
- dismiss();
}
+ dismiss();
});
View customView = getLayoutInflater().inflate(R.layout.media_route_controller_dialog, null);
setView(customView, 0, 0, 0, 0);
@@ -160,8 +130,8 @@
if (customPanelView != null) {
customPanelView.setMinimumHeight(0);
}
- mVolumeLayout = (LinearLayout) customView.findViewById(R.id.media_route_volume_layout);
- mVolumeSlider = (SeekBar) customView.findViewById(R.id.media_route_volume_slider);
+ mVolumeLayout = customView.findViewById(R.id.media_route_volume_layout);
+ mVolumeSlider = customView.findViewById(R.id.media_route_volume_slider);
mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
private final Runnable mStopTrackingTouch = new Runnable() {
@Override
@@ -199,11 +169,10 @@
});
mMediaRouteButtonDrawable = obtainMediaRouteButtonDrawable();
- mCreated = true;
if (update()) {
mControlView = onCreateMediaControlView(savedInstanceState);
FrameLayout controlFrame =
- (FrameLayout) customView.findViewById(R.id.media_route_control_frame);
+ customView.findViewById(R.id.media_route_control_frame);
if (mControlView != null) {
controlFrame.addView(mControlView);
controlFrame.setVisibility(View.VISIBLE);
@@ -261,8 +230,7 @@
Drawable icon = getIconDrawable();
if (icon != mCurrentIconDrawable) {
mCurrentIconDrawable = icon;
- if (icon instanceof AnimationDrawable) {
- AnimationDrawable animDrawable = (AnimationDrawable) icon;
+ if (icon instanceof AnimationDrawable animDrawable) {
if (!mAttachedToWindow && !mRoute.isConnecting()) {
// When the route is already connected before the view is attached, show the
// last frame of the connected animation immediately.
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index e3137e2..ac1e841 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -116,14 +116,14 @@
<public name="alternateLauncherIcons"/>
<!-- @FlaggedApi(android.content.pm.Flags.FLAG_CHANGE_LAUNCHER_BADGING) -->
<public name="alternateLauncherLabels"/>
- <!-- @hide Only for device overlay to use this. -->
- <public name="pointerIconVectorFill"/>
- <!-- @hide Only for device overlay to use this. -->
- <public name="pointerIconVectorFillInverse"/>
- <!-- @hide Only for device overlay to use this. -->
- <public name="pointerIconVectorStroke"/>
- <!-- @hide Only for device overlay to use this. -->
- <public name="pointerIconVectorStrokeInverse"/>
+ <!-- @hide Wrongly added here. -->
+ <public name="removed_pointerIconVectorFill"/>
+ <!-- @hide Wrongly added here. -->
+ <public name="removed_pointerIconVectorFillInverse"/>
+ <!-- @hide Wrongly added here. -->
+ <public name="removed_pointerIconVectorStroke"/>
+ <!-- @hide Wrongly added here. -->
+ <public name="removed_pointerIconVectorStrokeInverse"/>
</staging-public-group>
<staging-public-group type="id" first-id="0x01b20000">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ffcfce9..06861b11 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1726,10 +1726,12 @@
<java-symbol type="style" name="PointerIconVectorStyleFillBlue" />
<java-symbol type="style" name="PointerIconVectorStyleFillPurple" />
<java-symbol type="attr" name="pointerIconVectorFill" />
+ <java-symbol type="attr" name="pointerIconVectorFillInverse" />
<java-symbol type="style" name="PointerIconVectorStyleStrokeWhite" />
<java-symbol type="style" name="PointerIconVectorStyleStrokeBlack" />
<java-symbol type="style" name="PointerIconVectorStyleStrokeNone" />
<java-symbol type="attr" name="pointerIconVectorStroke" />
+ <java-symbol type="attr" name="pointerIconVectorStrokeInverse" />
<java-symbol type="style" name="TextAppearance.DeviceDefault.Notification.Title" />
<java-symbol type="style" name="TextAppearance.DeviceDefault.Notification.Info" />
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index c06ad64..4c49ff8 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -10,8 +10,8 @@
filegroup {
name: "FrameworksCoreTests-aidl",
srcs: [
- "src/**/I*.aidl",
"aidl/**/I*.aidl",
+ "src/**/I*.aidl",
],
visibility: ["//visibility:private"],
}
@@ -19,13 +19,13 @@
filegroup {
name: "FrameworksCoreTests-helpers",
srcs: [
- "DisabledTestApp/src/**/*.java",
- "EnabledTestApp/src/**/*.java",
+ "AppThatCallsBinderMethods/src/**/*.kt",
+ "BinderDeathRecipientHelperApp/src/**/*.java",
"BinderFrozenStateChangeCallbackTestApp/src/**/*.java",
"BinderProxyCountingTestApp/src/**/*.java",
"BinderProxyCountingTestService/src/**/*.java",
- "BinderDeathRecipientHelperApp/src/**/*.java",
- "AppThatCallsBinderMethods/src/**/*.kt",
+ "DisabledTestApp/src/**/*.java",
+ "EnabledTestApp/src/**/*.java",
],
visibility: ["//visibility:private"],
}
@@ -45,11 +45,11 @@
defaults: ["FrameworksCoreTests-resources"],
srcs: [
- "src/**/*.java",
- "src/**/*.kt",
+ ":FrameworksCoreTestDoubles-sources",
":FrameworksCoreTests-aidl",
":FrameworksCoreTests-helpers",
- ":FrameworksCoreTestDoubles-sources",
+ "src/**/*.java",
+ "src/**/*.kt",
],
aidl: {
@@ -65,74 +65,74 @@
"-c fa",
],
static_libs: [
- "collector-device-lib-platform",
- "frameworks-base-testutils",
- "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
- "core-tests-support",
- "cts-input-lib",
+ "TestParameterInjector",
"android-common",
- "frameworks-core-util-lib",
- "mockwebserver",
- "guava",
- "guava-android-testlib",
"android.app.usage.flags-aconfig-java",
+ "android.content.res.flags-aconfig-java",
+ "android.security.flags-aconfig-java",
"android.view.accessibility.flags-aconfig-java",
"androidx.core_core",
"androidx.core_core-ktx",
"androidx.test.core",
"androidx.test.espresso.core",
"androidx.test.ext.junit",
- "androidx.test.runner",
"androidx.test.rules",
- "flag-junit",
- "junit-params",
- "kotlin-test",
- "mockito-target-minus-junit4",
+ "androidx.test.runner",
"androidx.test.uiautomator_uiautomator",
- "platform-parametric-runner-lib",
- "platform-test-annotations",
- "platform-compat-test-rules",
- "truth",
- "print-test-util-lib",
- "testng",
- "servicestests-utils",
- "device-time-shell-utils",
- "testables",
+ "collector-device-lib-platform",
"com.android.text.flags-aconfig-java",
+ "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
+ "core-tests-support",
+ "cts-input-lib",
+ "device-time-shell-utils",
"flag-junit",
- "ravenwood-junit",
- "perfetto_trace_java_protos",
+ "flag-junit",
"flickerlib-parsers",
"flickerlib-trace_processor_shell",
- "mockito-target-extended-minus-junit4",
- "TestParameterInjector",
- "android.content.res.flags-aconfig-java",
- "android.security.flags-aconfig-java",
+ "frameworks-base-testutils",
+ "frameworks-core-util-lib",
+ "guava",
+ "guava-android-testlib",
+ "junit-params",
+ "kotlin-test",
"mockito-kotlin2",
+ "mockito-target-extended-minus-junit4",
+ "mockito-target-minus-junit4",
+ "mockwebserver",
+ "perfetto_trace_java_protos",
+ "platform-compat-test-rules",
+ "platform-parametric-runner-lib",
+ "platform-test-annotations",
+ "print-test-util-lib",
+ "ravenwood-junit",
+ "servicestests-utils",
+ "testables",
+ "testng",
+ "truth",
],
libs: [
- "android.test.runner.stubs",
- "org.apache.http.legacy.stubs",
"android.test.base.stubs",
"android.test.mock.stubs",
- "framework",
- "ext",
- "framework-res",
+ "android.test.runner.stubs",
"android.view.flags-aconfig-java",
+ "ext",
+ "framework",
+ "framework-res",
+ "org.apache.http.legacy.stubs",
],
jni_libs: [
+ "libAppOpsTest_jni",
"libpowermanagertest_jni",
"libviewRootImplTest_jni",
"libworksourceparceltest_jni",
- "libAppOpsTest_jni",
],
sdk_version: "core_platform",
test_suites: [
- "device-tests",
- "device-platinum-tests",
"automotive-tests",
+ "device-platinum-tests",
+ "device-tests",
],
certificate: "platform",
@@ -141,21 +141,21 @@
java_resources: [":FrameworksCoreTests_unit_test_cert_der"],
data: [
+ ":AppThatCallsBinderMethods",
+ ":AppThatUsesAppOps",
":BinderDeathRecipientHelperApp1",
":BinderDeathRecipientHelperApp2",
- ":com.android.cts.helpers.aosp",
":BinderFrozenStateChangeCallbackTestApp",
":BinderProxyCountingTestApp",
":BinderProxyCountingTestService",
- ":AppThatUsesAppOps",
- ":AppThatCallsBinderMethods",
- ":HelloWorldSdk1",
- ":HelloWorldUsingSdk1AndSdk1",
- ":HelloWorldUsingSdk1And2",
- ":HelloWorldUsingSdkMalformedNegativeVersion",
":CtsStaticSharedLibConsumerApp1",
":CtsStaticSharedLibConsumerApp3",
":CtsStaticSharedLibProviderApp1",
+ ":HelloWorldSdk1",
+ ":HelloWorldUsingSdk1And2",
+ ":HelloWorldUsingSdk1AndSdk1",
+ ":HelloWorldUsingSdkMalformedNegativeVersion",
+ ":com.android.cts.helpers.aosp",
],
}
@@ -170,8 +170,8 @@
// FrameworksCoreTestsRavenwood references the .aapt.srcjar
use_resource_processor: false,
libs: [
- "framework-res",
"android.test.runner.stubs",
+ "framework-res",
"org.apache.http.legacy.stubs",
],
uses_libs: [
@@ -231,16 +231,16 @@
static_libs: [
"androidx.test.espresso.core",
"androidx.test.ext.junit",
- "androidx.test.runner",
"androidx.test.rules",
+ "androidx.test.runner",
"mockito-target-minus-junit4",
"truth",
],
libs: [
- "android.test.runner.stubs.system",
"android.test.base.stubs.system",
"android.test.mock.stubs.system",
+ "android.test.runner.stubs.system",
"framework",
"framework-res",
],
@@ -249,43 +249,43 @@
android_ravenwood_test {
name: "FrameworksCoreTestsRavenwood",
libs: [
- "android.test.runner.stubs.system",
"android.test.base.stubs.system",
+ "android.test.runner.stubs.system",
],
static_libs: [
- "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
+ "androidx.annotation_annotation",
"androidx.core_core",
"androidx.core_core-ktx",
- "androidx.annotation_annotation",
- "androidx.test.rules",
"androidx.test.ext.junit",
+ "androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt-ravenwood",
+ "core-test-rules", // for libcore.dalvik.system.CloseGuardSupport
"flag-junit",
- "platform-test-annotations",
+ "flag-junit",
"perfetto_trace_java_protos",
- "flag-junit",
+ "platform-test-annotations",
"testng",
],
srcs: [
"src/android/app/ActivityManagerTest.java",
+ "src/android/app/PropertyInvalidatedCacheTests.java",
"src/android/colormodel/CamTest.java",
"src/android/content/ContextTest.java",
+ "src/android/content/TestComponentCallbacks2.java",
"src/android/content/pm/PackageManagerTest.java",
"src/android/content/pm/UserInfoTest.java",
- "src/android/app/PropertyInvalidatedCacheTests.java",
- "src/android/database/CursorWindowTest.java",
- "src/android/os/**/*.java",
"src/android/content/res/*.java",
"src/android/content/res/*.kt",
+ "src/android/database/CursorWindowTest.java",
+ "src/android/os/**/*.java",
"src/android/telephony/PinResultTest.java",
"src/android/util/**/*.java",
"src/android/view/DisplayAdjustmentsTests.java",
- "src/android/view/DisplayTest.java",
"src/android/view/DisplayInfoTest.java",
+ "src/android/view/DisplayTest.java",
"src/com/android/internal/logging/**/*.java",
"src/com/android/internal/os/**/*.java",
- "src/com/android/internal/util/**/*.java",
"src/com/android/internal/power/EnergyConsumerStatsTest.java",
"src/com/android/internal/ravenwood/**/*.java",
@@ -293,10 +293,12 @@
// to avoid having a dependency to FrameworksCoreTests.
// This way, when updating source files and running this test, we don't need to
// rebuild the entire FrameworksCoreTests, which would be slow.
- ":FrameworksCoreTests-resonly{.aapt.srcjar}",
+ "src/com/android/internal/util/**/*.java",
+
+ ":FrameworksCoreTestDoubles-sources",
":FrameworksCoreTests-aidl",
":FrameworksCoreTests-helpers",
- ":FrameworksCoreTestDoubles-sources",
+ ":FrameworksCoreTests-resonly{.aapt.srcjar}",
],
exclude_srcs: [
"src/android/content/res/FontScaleConverterActivityTest.java",
@@ -320,8 +322,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_annotations: ["android.platform.test.annotations.Presubmit"],
}
@@ -331,12 +333,12 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "com.android.internal.inputmethod",
"android.view.inputmethod",
+ "com.android.internal.inputmethod",
],
exclude_annotations: ["androidx.test.filters.FlakyTest"],
}
@@ -346,8 +348,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.content.ContextTest"],
}
@@ -357,8 +359,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.app.KeyguardManagerTest"],
}
@@ -368,8 +370,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.app.PropertyInvalidatedCacheTests"],
}
@@ -379,12 +381,12 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "android.content.ContextTest",
"android.content.ComponentCallbacksControllerTest",
+ "android.content.ContextTest",
"android.content.ContextWrapperTest",
],
}
@@ -394,8 +396,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.database.sqlite.SQLiteRawStatementTest"],
}
@@ -405,8 +407,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.net"],
include_annotations: ["android.platform.test.annotations.Presubmit"],
@@ -417,8 +419,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.os.BatteryStatsTests"],
exclude_annotations: ["com.android.internal.os.SkipPresubmit"],
@@ -429,8 +431,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.os.EnvironmentTest"],
}
@@ -440,12 +442,12 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "com.android.internal.util.FastDataTest",
"android.util.CharsetUtilsTest",
+ "com.android.internal.util.FastDataTest",
],
}
@@ -454,12 +456,12 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "android.util.XmlTest",
"android.util.BinaryXmlTest",
+ "android.util.XmlTest",
],
}
@@ -468,8 +470,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.util.apk.SourceStampVerifierTest"],
}
@@ -479,8 +481,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.view.textclassifier"],
exclude_annotations: ["androidx.test.filters.FlakyTest"],
@@ -491,13 +493,13 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.app."],
exclude_filters: [
- "com.android.internal.app.WindowDecorActionBarTest",
"com.android.internal.app.IntentForwarderActivityTest",
+ "com.android.internal.app.WindowDecorActionBarTest",
],
}
@@ -506,8 +508,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.content."],
}
@@ -517,8 +519,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.infra."],
}
@@ -528,8 +530,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.jank"],
}
@@ -539,16 +541,16 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "android.os.BinderProxyTest",
"android.os.BinderDeathRecipientTest",
"android.os.BinderFrozenStateChangeNotificationTest",
"android.os.BinderProxyCountingTest",
- "android.os.BinderUncaughtExceptionHandlerTest",
+ "android.os.BinderProxyTest",
"android.os.BinderThreadPriorityTest",
+ "android.os.BinderUncaughtExceptionHandlerTest",
"android.os.BinderWorkSourceTest",
"android.os.ParcelNullabilityTest",
"android.os.ParcelTest",
@@ -562,13 +564,13 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "com.android.internal.os.KernelCpuUidClusterTimeReaderTest",
- "com.android.internal.os.KernelCpuUidBpfMapReaderTest",
"com.android.internal.os.KernelCpuUidActiveTimeReaderTest",
+ "com.android.internal.os.KernelCpuUidBpfMapReaderTest",
+ "com.android.internal.os.KernelCpuUidClusterTimeReaderTest",
"com.android.internal.os.KernelCpuUidFreqTimeReaderTest",
"com.android.internal.os.KernelSingleUidTimeReaderTest",
],
@@ -579,8 +581,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.server.power.stats.BstatsCpuTimesValidationTest"],
}
@@ -590,8 +592,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.security."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
@@ -602,8 +604,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.util.LatencyTrackerTest"],
}
@@ -613,8 +615,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.content.ContentCaptureOptionsTest"],
}
@@ -624,8 +626,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.content.integrity."],
}
@@ -635,8 +637,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.content.pm."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
@@ -647,8 +649,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.content.pm."],
include_annotations: ["android.platform.test.annotations.Postsubmit"],
@@ -659,14 +661,14 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.content.res."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
exclude_annotations: [
- "androidx.test.filters.FlakyTest",
"android.platform.test.annotations.Postsubmit",
+ "androidx.test.filters.FlakyTest",
"org.junit.Ignore",
],
}
@@ -676,8 +678,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.content.res."],
include_annotations: ["android.platform.test.annotations.Postsubmit"],
@@ -688,17 +690,17 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
+ "android.service.controls",
+ "android.service.controls.actions",
+ "android.service.controls.templates",
"android.service.euicc",
"android.service.notification",
"android.service.quicksettings",
"android.service.settings.suggestions",
- "android.service.controls.templates",
- "android.service.controls.actions",
- "android.service.controls",
],
exclude_annotations: ["org.junit.Ignore"],
}
@@ -708,8 +710,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.view.contentcapture"],
}
@@ -719,8 +721,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.view.contentprotection"],
}
@@ -730,8 +732,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.content."],
include_annotations: ["android.platform.test.annotations.Presubmit"],
@@ -742,8 +744,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.graphics.drawable.IconTest"],
}
@@ -753,13 +755,13 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "com.android.internal.accessibility",
"android.accessibilityservice",
"android.view.accessibility",
+ "com.android.internal.accessibility",
],
}
@@ -768,8 +770,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.app.usage"],
}
@@ -779,8 +781,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["com.android.internal.util.FastDataTest"],
}
@@ -790,8 +792,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: ["android.hardware.input"],
}
@@ -801,12 +803,12 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
- "android.view.VerifiedMotionEventTest",
"android.view.VerifiedKeyEventTest",
+ "android.view.VerifiedMotionEventTest",
],
}
@@ -839,8 +841,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_filters: [
"com.android.internal.jank.FrameTrackerTest",
@@ -854,8 +856,8 @@
base: "FrameworksCoreTests",
test_suites: [
"automotive-tests",
- "device-tests",
"device-platinum-tests",
+ "device-tests",
],
include_annotations: ["android.platform.test.annotations.PlatinumTest"],
}
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index a02af78..2505500 100644
--- a/core/tests/coretests/src/android/content/ContextTest.java
+++ b/core/tests/coretests/src/android/content/ContextTest.java
@@ -23,6 +23,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -35,17 +36,24 @@
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.ImageReader;
+import android.os.Looper;
import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.DisabledOnRavenwood;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.ravenwood.RavenwoodRule;
import android.view.Display;
+import android.window.WindowTokenClient;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.window.flags.Flags;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -61,6 +69,9 @@
@Rule
public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder().build();
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Test
public void testInstrumentationContext() {
// Confirm that we have a valid Context
@@ -280,4 +291,44 @@
return appContext.createDisplayContext(display)
.createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
}
+
+ @Test
+ @DisabledOnRavenwood(blockedBy = Context.class)
+ @DisableFlags(Flags.FLAG_TRACK_SYSTEM_UI_CONTEXT_BEFORE_WMS)
+ public void testSysUiContextRegisterComponentCallbacks_disableFlag() {
+ Looper.prepare();
+
+ // Use createSystemActivityThreadForTesting to initialize
+ // systemUiContext#getApplicationContext.
+ final Context systemUiContext = ActivityThread.createSystemActivityThreadForTesting()
+ .getSystemUiContext();
+ final TestComponentCallbacks2 callbacks = new TestComponentCallbacks2();
+ systemUiContext.registerComponentCallbacks(callbacks);
+
+ final WindowTokenClient windowTokenClient =
+ (WindowTokenClient) systemUiContext.getWindowContextToken();
+ windowTokenClient.onConfigurationChanged(Configuration.EMPTY, DEFAULT_DISPLAY);
+
+ assertWithMessage("ComponentCallbacks should delegate to the app Context "
+ + "if the flag is disabled.").that(callbacks.mConfiguration).isNull();
+ }
+
+ @Test
+ @DisabledOnRavenwood(blockedBy = Context.class)
+ @EnableFlags(Flags.FLAG_TRACK_SYSTEM_UI_CONTEXT_BEFORE_WMS)
+ public void testSysUiContextRegisterComponentCallbacks_enableFlag() {
+ final Context systemUiContext = ActivityThread.currentActivityThread()
+ .createSystemUiContextForTesting(DEFAULT_DISPLAY);
+ final TestComponentCallbacks2 callbacks = new TestComponentCallbacks2();
+ final Configuration config = Configuration.EMPTY;
+
+ systemUiContext.registerComponentCallbacks(callbacks);
+
+ final WindowTokenClient windowTokenClient =
+ (WindowTokenClient) systemUiContext.getWindowContextToken();
+ windowTokenClient.onConfigurationChanged(config, DEFAULT_DISPLAY);
+
+ assertWithMessage("ComponentCallbacks should delegate to SystemUiContext "
+ + "if the flag is enabled.").that(callbacks.mConfiguration).isEqualTo(config);
+ }
}
diff --git a/data/keyboards/Vendor_0957_Product_0001.kl b/data/keyboards/Vendor_0957_Product_0001.kl
index 87cb942..0241f36 100644
--- a/data/keyboards/Vendor_0957_Product_0001.kl
+++ b/data/keyboards/Vendor_0957_Product_0001.kl
@@ -72,6 +72,8 @@
key usage 0x000c008D GUIDE
key usage 0x000c0089 TV
+key usage 0x000c0187 FEATURED_APP_1 WAKE #FreeTv
+
key usage 0x000c009C CHANNEL_UP
key usage 0x000c009D CHANNEL_DOWN
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
index 126ab3d..14338a4 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/DesktopModeCompatPolicy.kt
@@ -24,7 +24,6 @@
import android.content.pm.ActivityInfo.OVERRIDE_EXCLUDE_CAPTION_INSETS_FROM_APP_BOUNDS
import android.window.DesktopModeFlags
import com.android.internal.R
-import com.android.window.flags.Flags
/**
* Class to decide whether to apply app compat policies in desktop mode.
@@ -64,7 +63,7 @@
* is enabled.
*/
fun shouldExcludeCaptionFromAppBounds(taskInfo: TaskInfo): Boolean =
- Flags.excludeCaptionFromAppBounds()
+ DesktopModeFlags.EXCLUDE_CAPTION_FROM_APP_BOUNDS.isTrue
&& isAnyForceConsumptionFlagsEnabled()
&& taskInfo.topActivityInfo?.let {
isInsetsCoupledWithConfiguration(it) && (!taskInfo.isResizeable || it.isChangeEnabled(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
index 9b850de6..c5ee313 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUtils.kt
@@ -33,6 +33,7 @@
import com.android.wm.shell.R
import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.common.DisplayLayout
+import kotlin.math.ceil
val DESKTOP_MODE_INITIAL_BOUNDS_SCALE: Float =
SystemProperties.getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f
@@ -190,22 +191,22 @@
val finalWidth: Int
// Get orientation either through top activity or task's orientation
if (taskInfo.hasPortraitTopActivity()) {
- val tempWidth = (targetHeight / aspectRatio).toInt()
+ val tempWidth = ceil(targetHeight / aspectRatio).toInt()
if (tempWidth <= targetWidth) {
finalHeight = targetHeight
finalWidth = tempWidth
} else {
finalWidth = targetWidth
- finalHeight = (finalWidth * aspectRatio).toInt()
+ finalHeight = ceil(finalWidth * aspectRatio).toInt()
}
} else {
- val tempWidth = (targetHeight * aspectRatio).toInt()
+ val tempWidth = ceil(targetHeight * aspectRatio).toInt()
if (tempWidth <= targetWidth) {
finalHeight = targetHeight
finalWidth = tempWidth
} else {
finalWidth = targetWidth
- finalHeight = (finalWidth / aspectRatio).toInt()
+ finalHeight = ceil(finalWidth / aspectRatio).toInt()
}
}
return Size(finalWidth, finalHeight + captionInsets)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index e2c3dda..fcd92ac 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -285,7 +285,7 @@
private val DEFAULT_PORTRAIT_BOUNDS = Rect(200, 165, 1400, 2085)
private val RESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 435, 1575, 1635)
private val RESIZABLE_PORTRAIT_BOUNDS = Rect(680, 75, 1880, 1275)
- private val UNRESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 449, 1575, 1611)
+ private val UNRESIZABLE_LANDSCAPE_BOUNDS = Rect(25, 448, 1575, 1611)
private val UNRESIZABLE_PORTRAIT_BOUNDS = Rect(830, 75, 1730, 1275)
private val wallpaperToken = MockToken().token()
private val homeComponentName = ComponentName(HOME_LAUNCHER_PACKAGE_NAME, /* class */ "")
@@ -2900,7 +2900,10 @@
}
@Test
- @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PIP)
+ @EnableFlags(
+ FLAG_ENABLE_DESKTOP_WINDOWING_PIP,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ )
fun onDesktopWindowClose_minimizedPipNotPresent_exitDesktop() {
val freeformTask = setUpFreeformTask()
val pipTask = setUpPipTask(autoEnterEnabled = true)
@@ -2915,10 +2918,8 @@
val wct = WindowContainerTransaction()
controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, freeformTask)
- // Remove wallpaper operation
- wct.hierarchyOps.any { hop ->
- hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
- }
+ // Moves wallpaper activity to back when leaving desktop
+ wct.assertReorder(wallpaperToken, toTop = false)
}
@Test
@@ -3224,6 +3225,24 @@
}
@Test
+ fun onDesktopWindowMinimize_triesToStopTiling() {
+ val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
+ val transition = Binder()
+ whenever(
+ freeformTaskTransitionStarter.startMinimizedModeTransition(
+ any(),
+ anyInt(),
+ anyBoolean(),
+ )
+ )
+ .thenReturn(transition)
+
+ controller.minimizeTask(task, MinimizeReason.MINIMIZE_BUTTON)
+
+ verify(snapEventHandler).removeTaskIfTiled(eq(DEFAULT_DISPLAY), eq(task.taskId))
+ }
+
+ @Test
fun handleRequest_fullscreenTask_freeformVisible_returnSwitchToFreeformWCT() {
val homeTask = setUpHomeTask()
val freeformTask = setUpFreeformTask()
@@ -4338,7 +4357,10 @@
}
@Test
- @EnableFlags(FLAG_ENABLE_DESKTOP_WINDOWING_PIP)
+ @EnableFlags(
+ FLAG_ENABLE_DESKTOP_WINDOWING_PIP,
+ Flags.FLAG_ENABLE_DESKTOP_WALLPAPER_ACTIVITY_FOR_SYSTEM_USER,
+ )
fun moveFocusedTaskToFullscreen_minimizedPipPresent_removeWallpaperActivity() {
val freeformTask = setUpFreeformTask()
val pipTask = setUpPipTask(autoEnterEnabled = true)
@@ -4356,10 +4378,8 @@
val taskChange = assertNotNull(wct.changes[freeformTask.token.asBinder()])
assertThat(taskChange.windowingMode)
.isEqualTo(WINDOWING_MODE_UNDEFINED) // inherited FULLSCREEN
- // Remove wallpaper operation
- wct.hierarchyOps.any { hop ->
- hop.type == HIERARCHY_OP_TYPE_REMOVE_TASK && hop.container == wallpaperToken.asBinder()
- }
+ // Moves wallpaper activity to back when leaving desktop
+ wct.assertReorder(wallpaperToken, toTop = false)
}
@Test
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 1af3bc8..5590ca72 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -39,6 +39,7 @@
import android.system.StructStat;
import android.util.ArrayMap;
import android.util.Base64;
+import android.util.Dumpable;
import android.util.Log;
import com.android.tools.r8.keepanno.annotations.KeepTarget;
@@ -52,18 +53,24 @@
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Backup transport for stashing stuff into a known location on disk, and
* later restoring from there. For testing only.
+ *
+ * <p>Note: the quickest way to build and sync this class is:
+ * {@code m LocalTransport && adb install $OUT/system/priv-app/LocalTransport/LocalTransport.apk}
*/
public class LocalTransport extends BackupTransport {
- private static final String TAG = "LocalTransport";
- private static final boolean DEBUG = false;
+ static final String TAG = "LocalTransport";
+ static final boolean DEBUG = Log.isLoggable(TAG, Log.VERBOSE);
private static final String TRANSPORT_DIR_NAME
= "com.android.localtransport.LocalTransport";
@@ -124,6 +131,8 @@
}
public LocalTransport(Context context, LocalTransportParameters parameters) {
+ Log.i(TAG, "Creating LocalTransport for user " + context.getUserId()
+ + " (DEBUG=" + DEBUG + ")");
mContext = context;
mParameters = parameters;
makeDataDirs();
@@ -910,25 +919,70 @@
return mMonitor;
}
- private class TestBackupManagerMonitor extends BackupManagerMonitor {
+ private class TestBackupManagerMonitor extends BackupManagerMonitor implements Dumpable {
+
+ private final List<DataTypeResult> mReceivedResults = new ArrayList<>();
+ private int mNumberReceivedEvents;
+
@Override
public void onEvent(Bundle event) {
- if (event == null || !mParameters.logAgentResults()) {
+ if (event == null) {
+ if (DEBUG) {
+ Log.w(TAG, "onEvent() called with null");
+ }
return;
}
-
- if (event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID)
- == BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS) {
+ int eventId = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID);
+ if (eventId != BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS) {
+ if (DEBUG) Log.v(TAG, "ignoring event with id " + eventId);
+ return;
+ }
+ mNumberReceivedEvents++;
+ boolean logResults = mParameters.logAgentResults();
+ ArrayList<DataTypeResult> results = event.getParcelableArrayList(
+ BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS,
+ DataTypeResult.class);
+ int size = results.size();
+ if (size == 0) {
+ if (logResults) {
+ Log.i(TAG, "no agent_logging_results on event #" + mNumberReceivedEvents);
+ }
+ return;
+ }
+ if (logResults) {
Log.i(TAG, "agent_logging_results {");
- ArrayList<DataTypeResult> results = event.getParcelableArrayList(
- BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS,
- DataTypeResult.class);
- for (DataTypeResult result : results) {
+ }
+ for (int i = 0; i < size; i++) {
+ var result = results.get(i);
+ mReceivedResults.add(result);
+ if (logResults) {
Log.i(TAG, "\t" + BackupRestoreEventLogger.toString(result));
}
+ }
+ if (logResults) {
Log.i(TAG, "}");
}
}
+
+ @Override
+ public void dump(PrintWriter pw, String[] args) {
+ pw.println("TestBackupManagerMonitor");
+ pw.printf("%d events received", mNumberReceivedEvents);
+ if (mNumberReceivedEvents == 0) {
+ pw.println();
+ return;
+ }
+ int size = mReceivedResults.size();
+ if (size == 0) {
+ pw.println("; no results on them");
+ return;
+ }
+ pw.printf("; %d results on them:\n", size);
+ for (int i = 0; i < size; i++) {
+ DataTypeResult result = mReceivedResults.get(i);
+ pw.printf(" #%d: %s\n", i, BackupRestoreEventLogger.toString(result));
+ }
+ }
}
@NonNull
@@ -941,4 +995,60 @@
}
return mParameters.noRestrictedModePackages();
}
+
+ @Override
+ public String toString() {
+ try {
+ try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
+ dump(pw, /* args= */ null);
+ pw.flush();
+ return sw.toString();
+ }
+ } catch (IOException e) {
+ // Shouldn't happen...
+ Log.e(TAG, "toString(): failed to dump", e);
+ return super.toString();
+ }
+ }
+
+ void dump(PrintWriter pw, String[] args) {
+ pw.printf("mDataDir: %s\n", mDataDir);
+ pw.printf("mCurrentSetDir: %s\n", mCurrentSetDir);
+ pw.printf("mCurrentSetIncrementalDir: %s\n", mCurrentSetIncrementalDir);
+ pw.printf("mCurrentSetFullDir: %s\n", mCurrentSetFullDir);
+
+ pw.printf("mRestorePackages: %s\n", Arrays.toString(mRestorePackages));
+ pw.printf("mRestorePackage: %d\n", mRestorePackage);
+ pw.printf("mRestoreType: %d\n", mRestoreType);
+ pw.printf("mRestoreSetDir: %s\n", mRestoreSetDir);
+ pw.printf("mRestoreSetIncrementalDir: %s\n", mRestoreSetIncrementalDir);
+ pw.printf("mRestoreSetFullDir: %s\n", mRestoreSetFullDir);
+
+ pw.printf("mFullTargetPackage: %s\n", mFullTargetPackage);
+ pw.printf("mSocket: %s\n", mSocket);
+ pw.printf("mSocketInputStream: %s\n", mSocketInputStream);
+ pw.printf("mFullBackupOutputStream: %s\n", mFullBackupOutputStream);
+ dumpByteArray(pw, "mFullBackupBuffer", mFullBackupBuffer);
+ pw.printf("mFullBackupSize: %d\n", mFullBackupSize);
+
+ pw.printf("mCurFullRestoreStream: %s\n", mCurFullRestoreStream);
+ dumpByteArray(pw, "mFullRestoreBuffer", mFullRestoreBuffer);
+ if (mParameters == null) {
+ pw.println("No LocalTransportParameters");
+ } else {
+ pw.println(mParameters);
+ }
+ if (mMonitor instanceof Dumpable) {
+ ((Dumpable) mMonitor).dump(pw, args);
+ }
+
+ pw.printf("currentDestinationString(): %s\n", currentDestinationString());
+ pw.printf("dataManagementIntent(): %s\n", dataManagementIntent());
+ pw.printf("dataManagementIntentLabel(): %s\n", dataManagementIntentLabel());
+ pw.printf("transportDirName(): %s\n", transportDirName());
+ }
+
+ private void dumpByteArray(PrintWriter pw, String name, byte[] array) {
+ pw.printf("%s size: %d\n", name, (array == null ? 0 : array.length));
+ }
}
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
index c980913..c7cfc5b 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportParameters.java
@@ -16,11 +16,15 @@
package com.android.localtransport;
+import static com.android.localtransport.LocalTransport.DEBUG;
+import static com.android.localtransport.LocalTransport.TAG;
+
import android.content.ContentResolver;
import android.os.Handler;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.KeyValueSettingObserver;
+import android.util.Log;
import java.util.Arrays;
import java.util.List;
@@ -76,15 +80,30 @@
}
public String getSettingValue(ContentResolver resolver) {
- return Settings.Secure.getString(resolver, SETTING);
+ String value = Settings.Secure.getString(resolver, SETTING);
+ if (DEBUG) {
+ Log.d(TAG, "LocalTransportParameters.getSettingValue(): returning " + value);
+ }
+ return value;
}
public void update(KeyValueListParser parser) {
- mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
- mIsNonIncrementalOnly = parser.getBoolean(KEY_NON_INCREMENTAL_ONLY, false);
- mIsDeviceTransfer = parser.getBoolean(KEY_IS_DEVICE_TRANSFER, false);
- mIsEncrypted = parser.getBoolean(KEY_IS_ENCRYPTED, false);
- mLogAgentResults = parser.getBoolean(KEY_LOG_AGENT_RESULTS, /* def */ false);
+ mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, /* def= */ false);
+ mIsNonIncrementalOnly = parser.getBoolean(KEY_NON_INCREMENTAL_ONLY, /* def= */ false);
+ mIsDeviceTransfer = parser.getBoolean(KEY_IS_DEVICE_TRANSFER, /* def= */ false);
+ mIsEncrypted = parser.getBoolean(KEY_IS_ENCRYPTED, /* def= */ false);
+ mLogAgentResults = parser.getBoolean(KEY_LOG_AGENT_RESULTS, /* def= */ false);
mNoRestrictedModePackages = parser.getString(KEY_NO_RESTRICTED_MODE_PACKAGES, /* def */ "");
}
+
+ @Override
+ public String toString() {
+ return "LocalTransportParameters[mFakeEncryptionFlag=" + mFakeEncryptionFlag
+ + ", mIsNonIncrementalOnly=" + mIsNonIncrementalOnly
+ + ", mIsDeviceTransfer=" + mIsDeviceTransfer
+ + ", mIsEncrypted=" + mIsEncrypted
+ + ", mLogAgentResults=" + mLogAgentResults
+ + ", noRestrictedModePackages()=" + noRestrictedModePackages()
+ + "]";
+ }
}
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransportService.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransportService.java
index ac4f418..2f6c57a 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransportService.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransportService.java
@@ -16,15 +16,28 @@
package com.android.localtransport;
+import static com.android.localtransport.LocalTransport.DEBUG;
+import static com.android.localtransport.LocalTransport.TAG;
+
+import android.annotation.Nullable;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
public class LocalTransportService extends Service {
- private static LocalTransport sTransport = null;
+
+ @Nullable
+ private static LocalTransport sTransport;
@Override
public void onCreate() {
+ if (DEBUG) {
+ Log.d(TAG, "LocalTransportService.onCreate()");
+ }
if (sTransport == null) {
LocalTransportParameters parameters =
new LocalTransportParameters(getMainThreadHandler(), getContentResolver());
@@ -35,11 +48,27 @@
@Override
public void onDestroy() {
+ if (DEBUG) {
+ Log.d(TAG, "LocalTransportService.onDestroy()");
+ }
sTransport.getParameters().stop();
}
@Override
public IBinder onBind(Intent intent) {
+ if (DEBUG) {
+ Log.d(TAG, "LocalTransportService.onBind(" + intent + "): parameters="
+ + sTransport.getParameters());
+ }
return sTransport.getBinder();
}
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (sTransport == null) {
+ pw.println("No sTransport");
+ return;
+ }
+ sTransport.dump(pw, args);
+ }
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
index c61a2ac..481023e 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/InstallLaunch.kt
@@ -16,9 +16,6 @@
package com.android.packageinstaller.v2.ui
-import android.app.Activity.RESULT_CANCELED
-import android.app.Activity.RESULT_FIRST_USER
-import android.app.Activity.RESULT_OK
import android.app.AppOpsManager
import android.content.ActivityNotFoundException
import android.content.Intent
@@ -67,6 +64,7 @@
InstallLaunch::class.java.packageName + ".callingPkgName"
private val LOG_TAG = InstallLaunch::class.java.simpleName
private const val TAG_DIALOG = "dialog"
+ private const val ARGS_SAVED_INTENT = "saved_intent"
}
/**
@@ -96,7 +94,15 @@
intent.getStringExtra(EXTRA_CALLING_PKG_NAME),
intent.getIntExtra(EXTRA_CALLING_PKG_UID, Process.INVALID_UID)
)
- installViewModel!!.preprocessIntent(intent, info)
+
+ var savedIntent: Intent? = null
+ if (savedInstanceState != null) {
+ savedIntent = savedInstanceState.getParcelable(ARGS_SAVED_INTENT, Intent::class.java)
+ }
+ if (!intent.filterEquals(savedIntent)) {
+ installViewModel!!.preprocessIntent(intent, info)
+ }
+
installViewModel!!.currentInstallStage.observe(this) { installStage: InstallStage ->
onInstallStageChange(installStage)
}
@@ -344,6 +350,11 @@
appOpsManager!!.stopWatchingMode(listener)
}
+ override fun onSaveInstanceState(outState: Bundle) {
+ outState.putParcelable(ARGS_SAVED_INTENT, intent)
+ super.onSaveInstanceState(outState)
+ }
+
override fun onDestroy() {
super.onDestroy()
while (activeUnknownSourcesListeners.isNotEmpty()) {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
index c4ca272..0a02845e 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/ui/UninstallLaunch.kt
@@ -16,7 +16,6 @@
package com.android.packageinstaller.v2.ui
-import android.app.Activity
import android.app.NotificationManager
import android.content.Intent
import android.os.Bundle
@@ -51,6 +50,7 @@
UninstallLaunch::class.java.packageName + ".callingActivityName"
val LOG_TAG = UninstallLaunch::class.java.simpleName
private const val TAG_DIALOG = "dialog"
+ private const val ARGS_SAVED_INTENT = "saved_intent"
}
private var uninstallViewModel: UninstallViewModel? = null
@@ -76,7 +76,15 @@
intent.getStringExtra(EXTRA_CALLING_ACTIVITY_NAME),
intent.getIntExtra(EXTRA_CALLING_PKG_UID, Process.INVALID_UID)
)
- uninstallViewModel!!.preprocessIntent(intent, callerInfo)
+
+ var savedIntent: Intent? = null
+ if (savedInstanceState != null) {
+ savedIntent = savedInstanceState.getParcelable(ARGS_SAVED_INTENT, Intent::class.java)
+ }
+ if (!intent.filterEquals(savedIntent)) {
+ uninstallViewModel!!.preprocessIntent(intent, callerInfo)
+ }
+
uninstallViewModel!!.currentUninstallStage.observe(this) { uninstallStage: UninstallStage ->
onUninstallStageChange(uninstallStage)
}
@@ -171,6 +179,11 @@
Log.d(LOG_TAG, "Cancelling uninstall")
}
uninstallViewModel!!.cancelUninstall()
- setResult(Activity.RESULT_FIRST_USER, null, true)
+ setResult(RESULT_FIRST_USER, null, true)
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ outState.putParcelable(ARGS_SAVED_INTENT, intent)
+ super.onSaveInstanceState(outState)
}
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt b/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt
index 388e03f..5a2b122 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/v2/viewmodel/InstallViewModel.kt
@@ -49,6 +49,20 @@
_currentInstallStage.value = installStage
}
}
+
+ // Since staging is an async operation, we will get the staging result later in time.
+ // Result of the file staging will be set in InstallRepository#mStagingResult.
+ // As such, mCurrentInstallStage will need to add another MutableLiveData
+ // as a data source
+ _currentInstallStage.addSource(
+ repository.stagingResult.distinctUntilChanged()
+ ) { installStage: InstallStage ->
+ if (installStage.stageCode != InstallStage.STAGE_READY) {
+ _currentInstallStage.value = installStage
+ } else {
+ checkIfAllowedAndInitiateInstall()
+ }
+ }
}
fun preprocessIntent(intent: Intent, callerInfo: InstallRepository.CallerInfo) {
@@ -56,18 +70,7 @@
if (stage.stageCode == InstallStage.STAGE_ABORTED) {
_currentInstallStage.value = stage
} else {
- // Since staging is an async operation, we will get the staging result later in time.
- // Result of the file staging will be set in InstallRepository#mStagingResult.
- // As such, mCurrentInstallStage will need to add another MutableLiveData
- // as a data source
repository.stageForInstall()
- _currentInstallStage.addSource(repository.stagingResult) { installStage: InstallStage ->
- if (installStage.stageCode != InstallStage.STAGE_READY) {
- _currentInstallStage.value = installStage
- } else {
- checkIfAllowedAndInitiateInstall()
- }
- }
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index a00484a..522a436 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -555,22 +555,17 @@
* connected 2) is Hearing Aid or LE Audio OR 3) connected profile matches currentAudioProfile
*
* @param cachedDevice the CachedBluetoothDevice
- * @param audioManager audio manager to get the current audio profile
+ * @param isOngoingCall get the current audio profile based on if in phone call
* @return if the device is AvailableMediaBluetoothDevice
*/
@WorkerThread
public static boolean isAvailableMediaBluetoothDevice(
- CachedBluetoothDevice cachedDevice, AudioManager audioManager) {
- int audioMode = audioManager.getMode();
+ CachedBluetoothDevice cachedDevice, boolean isOngoingCall) {
int currentAudioProfile;
- if (audioMode == AudioManager.MODE_RINGTONE
- || audioMode == AudioManager.MODE_IN_CALL
- || audioMode == AudioManager.MODE_IN_COMMUNICATION) {
- // in phone call
+ if (isOngoingCall) {
currentAudioProfile = BluetoothProfile.HEADSET;
} else {
- // without phone call
currentAudioProfile = BluetoothProfile.A2DP;
}
@@ -859,22 +854,17 @@
* currentAudioProfile
*
* @param cachedDevice the CachedBluetoothDevice
- * @param audioManager audio manager to get the current audio profile
+ * @param isOngoingCall get the current audio profile based on if in phone call
* @return if the device is AvailableMediaBluetoothDevice
*/
@WorkerThread
public static boolean isConnectedBluetoothDevice(
- CachedBluetoothDevice cachedDevice, AudioManager audioManager) {
- int audioMode = audioManager.getMode();
+ CachedBluetoothDevice cachedDevice, boolean isOngoingCall) {
int currentAudioProfile;
- if (audioMode == AudioManager.MODE_RINGTONE
- || audioMode == AudioManager.MODE_IN_CALL
- || audioMode == AudioManager.MODE_IN_COMMUNICATION) {
- // in phone call
+ if (isOngoingCall) {
currentAudioProfile = BluetoothProfile.HEADSET;
} else {
- // without phone call
currentAudioProfile = BluetoothProfile.A2DP;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 7c46db9..ebe6128 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -87,7 +87,6 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private BluetoothDevice mBluetoothDevice;
- @Mock private AudioManager mAudioManager;
@Mock private PackageManager mPackageManager;
@Mock private LeAudioProfile mA2dpProfile;
@Mock private LeAudioProfile mLeAudioProfile;
@@ -446,13 +445,12 @@
assertThat(
BluetoothUtils.isAvailableMediaBluetoothDevice(
- mCachedBluetoothDevice, mAudioManager))
+ mCachedBluetoothDevice, /* isOngoingCall= */ false))
.isTrue();
}
@Test
public void isAvailableMediaBluetoothDevice_isHeadset_isConnectedA2dpDevice_returnFalse() {
- when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
@@ -460,13 +458,12 @@
assertThat(
BluetoothUtils.isAvailableMediaBluetoothDevice(
- mCachedBluetoothDevice, mAudioManager))
+ mCachedBluetoothDevice, /* isOngoingCall= */ true))
.isFalse();
}
@Test
public void isAvailableMediaBluetoothDevice_isA2dp_isConnectedA2dpDevice_returnTrue() {
- when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
@@ -474,13 +471,12 @@
assertThat(
BluetoothUtils.isAvailableMediaBluetoothDevice(
- mCachedBluetoothDevice, mAudioManager))
+ mCachedBluetoothDevice, /* isOngoingCall= */ false))
.isTrue();
}
@Test
public void isAvailableMediaBluetoothDevice_isHeadset_isConnectedHfpDevice_returnTrue() {
- when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
@@ -488,7 +484,7 @@
assertThat(
BluetoothUtils.isAvailableMediaBluetoothDevice(
- mCachedBluetoothDevice, mAudioManager))
+ mCachedBluetoothDevice, /* isOngoingCall= */ true))
.isTrue();
}
@@ -499,56 +495,52 @@
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.isConnected()).thenReturn(true);
- assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice, mAudioManager))
- .isFalse();
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(
+ mCachedBluetoothDevice, /* isOngoingCall= */ false)).isFalse();
}
@Test
public void isConnectedBluetoothDevice_isHeadset_isConnectedA2dpDevice_returnTrue() {
- when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.isConnected()).thenReturn(true);
- assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice, mAudioManager))
- .isTrue();
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(
+ mCachedBluetoothDevice, /* isOngoingCall= */ true)).isTrue();
}
@Test
public void isConnectedBluetoothDevice_isA2dp_isConnectedA2dpDevice_returnFalse() {
- when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_NORMAL);
when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.isConnected()).thenReturn(true);
- assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice, mAudioManager))
- .isFalse();
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(
+ mCachedBluetoothDevice, /* isOngoingCall= */ false)).isFalse();
}
@Test
public void isConnectedBluetoothDevice_isHeadset_isConnectedHfpDevice_returnFalse() {
- when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.isConnected()).thenReturn(true);
- assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice, mAudioManager))
- .isFalse();
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(
+ mCachedBluetoothDevice, /* isOngoingCall= */ true)).isFalse();
}
@Test
public void isConnectedBluetoothDevice_isNotConnected_returnFalse() {
- when(mAudioManager.getMode()).thenReturn(AudioManager.MODE_RINGTONE);
when(mCachedBluetoothDevice.isConnectedA2dpDevice()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.isConnected()).thenReturn(false);
- assertThat(BluetoothUtils.isConnectedBluetoothDevice(mCachedBluetoothDevice, mAudioManager))
- .isFalse();
+ assertThat(BluetoothUtils.isConnectedBluetoothDevice(
+ mCachedBluetoothDevice, /* isOngoingCall= */ true)).isFalse();
}
@Test
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt
index fffc7f9..2d2a8154 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/UserActionDistanceScopeImpl.kt
@@ -16,6 +16,8 @@
package com.android.compose.animation.scene
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.MotionScheme
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
@@ -59,4 +61,8 @@
override val layoutDirection: LayoutDirection
get() = layoutImpl.layoutDirection
+
+ @ExperimentalMaterial3ExpressiveApi
+ override val motionScheme: MotionScheme
+ get() = layoutImpl.state.motionScheme
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
index e0b4218..613afe2 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
@@ -18,7 +18,8 @@
import androidx.compose.animation.core.Easing
import androidx.compose.animation.core.LinearEasing
-import androidx.compose.ui.geometry.Offset
+import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
+import androidx.compose.material3.MotionScheme
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.LayoutDirection
@@ -29,8 +30,8 @@
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.ElementStateScope
-import com.android.compose.animation.scene.Scale
import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.transformation.PropertyTransformation.Property
import kotlinx.coroutines.CoroutineScope
/** A transformation applied to one or more elements during a transition. */
@@ -126,9 +127,13 @@
): T
}
+@OptIn(ExperimentalMaterial3ExpressiveApi::class)
interface PropertyTransformationScope : Density, ElementStateScope {
/** The current [direction][LayoutDirection] of the layout. */
val layoutDirection: LayoutDirection
+
+ /** The [MotionScheme] in use by the [SceneTransitionLayout]. */
+ val motionScheme: MotionScheme
}
/** Defines the transformation-type to be applied to all elements matching [matcher]. */
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
index e4539b7..0b13900 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegateTest.java
@@ -45,7 +45,6 @@
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
-import android.os.Handler;
import android.platform.test.annotations.EnableFlags;
import android.provider.Settings;
import android.testing.TestableLooper;
@@ -75,6 +74,8 @@
import com.android.systemui.res.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.After;
import org.junit.Before;
@@ -107,6 +108,7 @@
private static final String TEST_LABEL = "label";
private static final int TEST_PRESET_INDEX = 1;
private static final String TEST_PRESET_NAME = "test_preset";
+ private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@Mock
private SystemUIDialogManager mSystemUIDialogManager;
@@ -150,11 +152,9 @@
private SystemUIDialog mDialog;
private SystemUIDialog.Factory mDialogFactory;
private HearingDevicesDialogDelegate mDialogDelegate;
- private TestableLooper mTestableLooper;
@Before
public void setUp() {
- mTestableLooper = TestableLooper.get(this);
when(mLocalBluetoothManager.getBluetoothAdapter()).thenReturn(mLocalBluetoothAdapter);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mProfileManager);
when(mProfileManager.getHapClientProfile()).thenReturn(mHapClientProfile);
@@ -186,6 +186,7 @@
public void clickPairNewDeviceButton_intentActionMatch() {
setUpDeviceDialogWithPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
getPairNewDeviceButton(mDialog).performClick();
@@ -232,6 +233,7 @@
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
assertToolsUi(0);
}
@@ -246,6 +248,7 @@
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
assertToolsUi(1);
}
@@ -267,6 +270,7 @@
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
assertToolsUi(2);
}
@@ -278,6 +282,7 @@
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
ViewGroup presetLayout = getPresetLayout(mDialog);
assertThat(presetLayout.getVisibility()).isEqualTo(View.GONE);
@@ -291,7 +296,7 @@
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
- mTestableLooper.processAllMessages();
+ mExecutor.runAllReady();
ViewGroup presetLayout = getPresetLayout(mDialog);
assertThat(presetLayout.getVisibility()).isEqualTo(View.VISIBLE);
@@ -306,6 +311,7 @@
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
ViewGroup ambientLayout = getAmbientLayout(mDialog);
assertThat(ambientLayout.getVisibility()).isEqualTo(View.GONE);
@@ -318,6 +324,7 @@
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
ViewGroup ambientLayout = getAmbientLayout(mDialog);
assertThat(ambientLayout.getVisibility()).isEqualTo(View.GONE);
@@ -343,6 +350,7 @@
public void onActiveDeviceChanged_presetExist_presetSelected() {
setUpDeviceDialogWithoutPairNewDeviceButton();
mDialog.show();
+ mExecutor.runAllReady();
BluetoothHapPresetInfo info = getTestPresetInfo();
when(mHapClientProfile.getAllPresetInfo(mDevice)).thenReturn(List.of(info));
when(mHapClientProfile.getActivePresetIndex(mDevice)).thenReturn(TEST_PRESET_INDEX);
@@ -351,7 +359,7 @@
assertThat(spinner.getSelectedItemPosition()).isEqualTo(-1);
mDialogDelegate.onActiveDeviceChanged(mCachedDevice, BluetoothProfile.LE_AUDIO);
- mTestableLooper.processAllMessages();
+ mExecutor.runAllReady();
ViewGroup presetLayout = getPresetLayout(mDialog);
assertThat(presetLayout.getVisibility()).isEqualTo(View.VISIBLE);
@@ -381,7 +389,8 @@
mActivityStarter,
mDialogTransitionAnimator,
mLocalBluetoothManager,
- new Handler(mTestableLooper.getLooper()),
+ mExecutor,
+ mExecutor,
mAudioManager,
mUiEventLogger
);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
index 438184d..22ecb0a 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java
@@ -30,7 +30,6 @@
import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Bundle;
-import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
@@ -49,6 +48,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -57,7 +57,6 @@
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.accessibility.hearingaid.HearingDevicesListAdapter.HearingDeviceItemCallback;
import com.android.systemui.animation.DialogTransitionAnimator;
import com.android.systemui.bluetooth.qsdialog.ActiveHearingDeviceItemFactory;
@@ -67,6 +66,7 @@
import com.android.systemui.bluetooth.qsdialog.DeviceItemFactory;
import com.android.systemui.bluetooth.qsdialog.DeviceItemType;
import com.android.systemui.bluetooth.qsdialog.SavedHearingDeviceItemFactory;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.res.R;
@@ -79,6 +79,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Executor;
import java.util.stream.Collectors;
/**
@@ -101,7 +102,8 @@
private final DialogTransitionAnimator mDialogTransitionAnimator;
private final ActivityStarter mActivityStarter;
private final LocalBluetoothManager mLocalBluetoothManager;
- private final Handler mMainHandler;
+ private final Executor mMainExecutor;
+ private final Executor mBgExecutor;
private final AudioManager mAudioManager;
private final LocalBluetoothProfileManager mProfileManager;
private final HearingDevicesUiEventLogger mUiEventLogger;
@@ -109,8 +111,6 @@
private final int mLaunchSourceId;
private SystemUIDialog mDialog;
-
- private List<DeviceItem> mHearingDeviceItemList;
private HearingDevicesListAdapter mDeviceListAdapter;
private View mPresetLayout;
@@ -122,14 +122,14 @@
@Override
public void onPresetInfoUpdated(List<BluetoothHapPresetInfo> presetInfos,
int activePresetIndex) {
- mMainHandler.post(
+ mMainExecutor.execute(
() -> refreshPresetUi(presetInfos, activePresetIndex));
}
@Override
public void onPresetCommandFailed(int reason) {
mPresetController.refreshPresetInfo();
- mMainHandler.post(() -> {
+ mMainExecutor.execute(() -> {
showErrorToast(R.string.hearing_devices_presets_error);
});
}
@@ -166,7 +166,8 @@
ActivityStarter activityStarter,
DialogTransitionAnimator dialogTransitionAnimator,
@Nullable LocalBluetoothManager localBluetoothManager,
- @Main Handler handler,
+ @Main Executor mainExecutor,
+ @Background Executor bgExecutor,
AudioManager audioManager,
HearingDevicesUiEventLogger uiEventLogger) {
mShowPairNewDevice = showPairNewDevice;
@@ -174,7 +175,8 @@
mActivityStarter = activityStarter;
mDialogTransitionAnimator = dialogTransitionAnimator;
mLocalBluetoothManager = localBluetoothManager;
- mMainHandler = handler;
+ mMainExecutor = mainExecutor;
+ mBgExecutor = bgExecutor;
mAudioManager = audioManager;
mProfileManager = localBluetoothManager.getProfileManager();
mUiEventLogger = uiEventLogger;
@@ -227,9 +229,10 @@
@Override
public void onActiveDeviceChanged(@Nullable CachedBluetoothDevice activeDevice,
int bluetoothProfile) {
- refreshDeviceUi();
- mMainHandler.post(() -> {
- CachedBluetoothDevice device = getActiveHearingDevice();
+ List<DeviceItem> hearingDeviceItemList = getHearingDeviceItemList();
+ refreshDeviceUi(hearingDeviceItemList);
+ mMainExecutor.execute(() -> {
+ CachedBluetoothDevice device = getActiveHearingDevice(hearingDeviceItemList);
if (mPresetController != null) {
mPresetController.setDevice(device);
mPresetLayout.setVisibility(
@@ -244,13 +247,15 @@
@Override
public void onProfileConnectionStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
int state, int bluetoothProfile) {
- refreshDeviceUi();
+ List<DeviceItem> hearingDeviceItemList = getHearingDeviceItemList();
+ refreshDeviceUi(hearingDeviceItemList);
}
@Override
public void onAclConnectionStateChanged(@NonNull CachedBluetoothDevice cachedDevice,
int state) {
- refreshDeviceUi();
+ List<DeviceItem> hearingDeviceItemList = getHearingDeviceItemList();
+ refreshDeviceUi(hearingDeviceItemList);
}
@Override
@@ -280,18 +285,25 @@
mUiEventLogger.log(HearingDevicesUiEvent.HEARING_DEVICES_DIALOG_SHOW, mLaunchSourceId);
- setupDeviceListView(dialog);
- setupPairNewDeviceButton(dialog);
- setupPresetSpinner(dialog);
- if (com.android.settingslib.flags.Flags.hearingDevicesAmbientVolumeControl()) {
- setupAmbientControls();
- }
- setupRelatedToolsView(dialog);
+ mBgExecutor.execute(() -> {
+ List<DeviceItem> hearingDeviceItemList = getHearingDeviceItemList();
+ CachedBluetoothDevice activeHearingDevice = getActiveHearingDevice(
+ hearingDeviceItemList);
+ mMainExecutor.execute(() -> {
+ setupDeviceListView(dialog, hearingDeviceItemList);
+ setupPairNewDeviceButton(dialog);
+ setupPresetSpinner(dialog, activeHearingDevice);
+ if (com.android.settingslib.flags.Flags.hearingDevicesAmbientVolumeControl()) {
+ setupAmbientControls(activeHearingDevice);
+ }
+ setupRelatedToolsView(dialog);
+ });
+ });
}
@Override
public void onStart(@NonNull SystemUIDialog dialog) {
- ThreadUtils.postOnBackgroundThread(() -> {
+ mBgExecutor.execute(() -> {
if (mLocalBluetoothManager != null) {
mLocalBluetoothManager.getEventManager().registerCallback(this);
}
@@ -306,7 +318,7 @@
@Override
public void onStop(@NonNull SystemUIDialog dialog) {
- ThreadUtils.postOnBackgroundThread(() -> {
+ mBgExecutor.execute(() -> {
if (mLocalBluetoothManager != null) {
mLocalBluetoothManager.getEventManager().unregisterCallback(this);
}
@@ -319,17 +331,18 @@
});
}
- private void setupDeviceListView(SystemUIDialog dialog) {
+ private void setupDeviceListView(SystemUIDialog dialog,
+ List<DeviceItem> hearingDeviceItemList) {
final RecyclerView deviceList = dialog.requireViewById(R.id.device_list);
deviceList.setLayoutManager(new LinearLayoutManager(dialog.getContext()));
- mHearingDeviceItemList = getHearingDeviceItemList();
- mDeviceListAdapter = new HearingDevicesListAdapter(mHearingDeviceItemList, this);
+ mDeviceListAdapter = new HearingDevicesListAdapter(hearingDeviceItemList, this);
deviceList.setAdapter(mDeviceListAdapter);
}
- private void setupPresetSpinner(SystemUIDialog dialog) {
+ private void setupPresetSpinner(SystemUIDialog dialog,
+ CachedBluetoothDevice activeHearingDevice) {
mPresetController = new HearingDevicesPresetsController(mProfileManager, mPresetCallback);
- mPresetController.setDevice(getActiveHearingDevice());
+ mPresetController.setDevice(activeHearingDevice);
mPresetSpinner = dialog.requireViewById(R.id.preset_spinner);
mPresetInfoAdapter = new HearingDevicesSpinnerAdapter(dialog.getContext());
@@ -367,12 +380,12 @@
mPresetLayout.setVisibility(mPresetController.isPresetControlAvailable() ? VISIBLE : GONE);
}
- private void setupAmbientControls() {
+ private void setupAmbientControls(CachedBluetoothDevice activeHearingDevice) {
final AmbientVolumeLayout ambientLayout = mDialog.requireViewById(R.id.ambient_layout);
mAmbientController = new AmbientVolumeUiController(
mDialog.getContext(), mLocalBluetoothManager, ambientLayout);
mAmbientController.setShowUiWhenLocalDataExist(false);
- mAmbientController.loadDevice(getActiveHearingDevice());
+ mAmbientController.loadDevice(activeHearingDevice);
}
private void setupPairNewDeviceButton(SystemUIDialog dialog) {
@@ -429,10 +442,11 @@
}
}
- private void refreshDeviceUi() {
- mHearingDeviceItemList = getHearingDeviceItemList();
- mMainHandler.post(() -> {
- mDeviceListAdapter.refreshDeviceItemList(mHearingDeviceItemList);
+ private void refreshDeviceUi(List<DeviceItem> hearingDeviceItemList) {
+ mMainExecutor.execute(() -> {
+ if (mDeviceListAdapter != null) {
+ mDeviceListAdapter.refreshDeviceItemList(hearingDeviceItemList);
+ }
});
}
@@ -463,21 +477,27 @@
}
@Nullable
- private CachedBluetoothDevice getActiveHearingDevice() {
- return mHearingDeviceItemList.stream()
+ private static CachedBluetoothDevice getActiveHearingDevice(
+ List<DeviceItem> hearingDeviceItemList) {
+ return hearingDeviceItemList.stream()
.filter(item -> item.getType() == DeviceItemType.ACTIVE_MEDIA_BLUETOOTH_DEVICE)
.map(DeviceItem::getCachedBluetoothDevice)
.findFirst()
.orElse(null);
}
+ @WorkerThread
private DeviceItem createHearingDeviceItem(CachedBluetoothDevice cachedDevice) {
final Context context = mDialog.getContext();
if (cachedDevice == null) {
return null;
}
+ int mode = mAudioManager.getMode();
+ boolean isOngoingCall = mode == AudioManager.MODE_RINGTONE
+ || mode == AudioManager.MODE_IN_CALL
+ || mode == AudioManager.MODE_IN_COMMUNICATION;
for (DeviceItemFactory itemFactory : mHearingDeviceItemFactoryList) {
- if (itemFactory.isFilterMatched(context, cachedDevice, mAudioManager)) {
+ if (itemFactory.isFilterMatched(context, cachedDevice, isOngoingCall)) {
return itemFactory.create(context, cachedDevice);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModel.kt
index ff2d9ef..1c9cf8d 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModel.kt
@@ -31,6 +31,7 @@
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.logging.UiEventLogger
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.systemui.Prefs
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
@@ -71,6 +72,7 @@
private val bluetoothStateInteractor: BluetoothStateInteractor,
private val bluetoothAutoOnInteractor: BluetoothAutoOnInteractor,
private val audioSharingInteractor: AudioSharingInteractor,
+ private val audioModeInteractor: AudioModeInteractor,
private val audioSharingButtonViewModelFactory: AudioSharingButtonViewModel.Factory,
private val bluetoothDeviceMetadataInteractor: BluetoothDeviceMetadataInteractor,
private val dialogTransitionAnimator: DialogTransitionAnimator,
@@ -167,6 +169,7 @@
// the device item list and animate the progress bar.
merge(
deviceItemInteractor.deviceItemUpdateRequest,
+ audioModeInteractor.isOngoingCall,
bluetoothDeviceMetadataInteractor.metadataUpdate,
if (
audioSharingInteractor.audioSharingAvailable() &&
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
index 095e6e7..bfbc27d 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactory.kt
@@ -18,7 +18,6 @@
import android.bluetooth.BluetoothDevice
import android.content.Context
-import android.media.AudioManager
import com.android.settingslib.bluetooth.BluetoothUtils
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
@@ -43,7 +42,7 @@
abstract fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean
@@ -51,8 +50,8 @@
fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
- ): Boolean = isFilterMatched(context, cachedDevice, audioManager, false)
+ isOngoingCall: Boolean,
+ ): Boolean = isFilterMatched(context, cachedDevice, isOngoingCall, false)
abstract fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem
@@ -88,11 +87,11 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
- BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager)
+ BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, isOngoingCall)
}
override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
@@ -113,10 +112,11 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return audioSharingAvailable &&
+ !isOngoingCall &&
BluetoothUtils.hasConnectedBroadcastSource(cachedDevice, localBluetoothManager)
}
@@ -140,11 +140,12 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return audioSharingAvailable &&
- super.isFilterMatched(context, cachedDevice, audioManager, true) &&
+ !isOngoingCall &&
+ super.isFilterMatched(context, cachedDevice, false, true) &&
BluetoothUtils.isAvailableAudioSharingMediaBluetoothDevice(
cachedDevice,
localBluetoothManager,
@@ -170,7 +171,7 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
@@ -182,11 +183,11 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return !BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
- BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, audioManager)
+ BluetoothUtils.isAvailableMediaBluetoothDevice(cachedDevice, isOngoingCall)
}
override fun create(context: Context, cachedDevice: CachedBluetoothDevice): DeviceItem {
@@ -206,7 +207,7 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return !BluetoothUtils.isActiveMediaDevice(cachedDevice) &&
@@ -218,14 +219,14 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
!BluetoothUtils.isExclusivelyManagedBluetoothDevice(context, cachedDevice.device) &&
- BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager)
+ BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, isOngoingCall)
} else {
- BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, audioManager)
+ BluetoothUtils.isConnectedBluetoothDevice(cachedDevice, isOngoingCall)
}
}
@@ -246,7 +247,7 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
@@ -275,7 +276,7 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
): Boolean {
return if (Flags.enableHideExclusivelyManagedBluetoothDevice()) {
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
index 1e0ba8e..b606c19 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt
@@ -19,10 +19,10 @@
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.content.Context
-import android.media.AudioManager
import com.android.settingslib.bluetooth.BluetoothCallback
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
@@ -39,6 +39,7 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.isActive
@@ -51,7 +52,6 @@
constructor(
private val bluetoothTileDialogRepository: BluetoothTileDialogRepository,
private val audioSharingInteractor: AudioSharingInteractor,
- private val audioManager: AudioManager,
private val bluetoothAdapter: BluetoothAdapter? = BluetoothAdapter.getDefaultAdapter(),
private val localBluetoothManager: LocalBluetoothManager?,
private val systemClock: SystemClock,
@@ -60,6 +60,7 @@
private val deviceItemDisplayPriority: List<@JvmSuppressWildcards DeviceItemType>,
@Application private val coroutineScope: CoroutineScope,
@Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val audioModeInteractor: AudioModeInteractor,
) {
private val mutableDeviceItemUpdate: MutableSharedFlow<List<DeviceItem>> =
@@ -118,8 +119,12 @@
internal suspend fun updateDeviceItems(context: Context, trigger: DeviceFetchTrigger) {
withContext(backgroundDispatcher) {
+ if (!isActive) {
+ return@withContext
+ }
val start = systemClock.elapsedRealtime()
val audioSharingAvailable = audioSharingInteractor.audioSharingAvailable()
+ val isOngoingCall = audioModeInteractor.isOngoingCall.first()
val deviceItems =
bluetoothTileDialogRepository.cachedDevices
.mapNotNull { cachedDevice ->
@@ -128,7 +133,7 @@
it.isFilterMatched(
context,
cachedDevice,
- audioManager,
+ isOngoingCall,
audioSharingAvailable,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpTouchHelper.java
index 3b6b9ed..47e725c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/headsup/HeadsUpTouchHelper.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.headsup;
+import android.annotation.Nullable;
import android.content.Context;
import android.os.RemoteException;
import android.view.MotionEvent;
@@ -210,10 +211,12 @@
if (mHeadsUpManager.shouldSwallowClick(
mPickedChild.getEntry().getSbn().getKey())) {
endMotion();
+ setTrackingHeadsUp(false);
return true;
}
}
endMotion();
+ setTrackingHeadsUp(false);
return false;
}
return false;
@@ -258,7 +261,7 @@
void setHeadsUpDraggingStartingHeight(int startHeight);
/** Sets notification that is being expanded. */
- void setTrackedHeadsUp(ExpandableNotificationRow expandableNotificationRow);
+ void setTrackedHeadsUp(@Nullable ExpandableNotificationRow expandableNotificationRow);
/** Called when a MotionEvent is about to trigger expansion. */
void startExpand(float newX, float newY, boolean startTracking, float expandedHeight);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 1568e9e..d383bee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2920,7 +2920,11 @@
if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
&& !mChildrenContainer.showingAsLowPriority()) {
final boolean wasExpanded = isGroupExpanded();
- mGroupExpansionManager.setGroupExpanded(mEntry, userExpanded);
+ if (NotificationBundleUi.isEnabled()) {
+ mGroupExpansionManager.setGroupExpanded(mEntryAdapter, userExpanded);
+ } else {
+ mGroupExpansionManager.setGroupExpanded(mEntry, userExpanded);
+ }
onExpansionChanged(true /* userAction */, wasExpanded);
return;
}
@@ -3399,7 +3403,11 @@
public void makeActionsVisibile() {
setUserExpanded(true, true);
if (isChildInGroup()) {
- mGroupExpansionManager.setGroupExpanded(mEntry, true);
+ if (NotificationBundleUi.isEnabled()) {
+ mGroupExpansionManager.setGroupExpanded(mEntryAdapter, true);
+ } else {
+ mGroupExpansionManager.setGroupExpanded(mEntry, true);
+ }
}
notifyHeightChanged(/* needsAnimation= */ false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 3ee8273..c694a19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -3644,6 +3644,9 @@
mScrollViewFields.sendCurrentGestureInGuts(false);
mScrollViewFields.sendCurrentGestureOverscroll(false);
setIsBeingDragged(false);
+ // dispatch to touchHandlers, so they can still finalize a previously started
+ // motion, while the shade is being dragged
+ return super.dispatchTouchEvent(ev);
}
return false;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModelTest.kt
index bfc5361..f04fc86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/BluetoothDetailsContentViewModelTest.kt
@@ -43,6 +43,7 @@
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -146,6 +147,7 @@
)
),
kosmos.audioSharingInteractor,
+ kosmos.audioModeInteractor,
kosmos.audioSharingButtonViewModelFactory,
bluetoothDeviceMetadataInteractor,
mDialogTransitionAnimator,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
index 0aa5199..7c8822b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemFactoryTest.kt
@@ -18,7 +18,6 @@
import android.bluetooth.BluetoothDevice
import android.graphics.drawable.Drawable
-import android.media.AudioManager
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
@@ -61,8 +60,6 @@
private val connectedDeviceItemFactory = ConnectedDeviceItemFactory()
private val savedDeviceItemFactory = SavedDeviceItemFactory()
- private val audioManager = context.getSystemService(AudioManager::class.java)!!
-
@Before
fun setup() {
mockitoSession =
@@ -132,7 +129,12 @@
fun testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_flagOff_returnsFalse() {
assertThat(
AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager)
- .isFilterMatched(context, cachedDevice, audioManager, false)
+ .isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ audioSharingAvailable = false,
+ )
)
.isFalse()
}
@@ -143,7 +145,12 @@
assertThat(
AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager)
- .isFilterMatched(context, cachedDevice, audioManager, true)
+ .isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ audioSharingAvailable = true,
+ )
)
.isFalse()
}
@@ -157,7 +164,26 @@
assertThat(
AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager)
- .isFilterMatched(context, cachedDevice, audioManager, true)
+ .isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ audioSharingAvailable = true,
+ )
+ )
+ .isFalse()
+ }
+
+ @Test
+ fun testAvailableAudioSharingMediaDeviceItemFactory_isFilterMatched_inCall_false() {
+ assertThat(
+ AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager)
+ .isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = true,
+ audioSharingAvailable = true,
+ )
)
.isFalse()
}
@@ -171,7 +197,12 @@
assertThat(
AvailableAudioSharingMediaDeviceItemFactory(localBluetoothManager)
- .isFilterMatched(context, cachedDevice, audioManager, true)
+ .isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ audioSharingAvailable = true,
+ )
)
.isTrue()
}
@@ -182,7 +213,9 @@
`when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
`when`(cachedDevice.isConnected).thenReturn(false)
- assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
+ )
.isTrue()
}
@@ -192,7 +225,9 @@
`when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
`when`(cachedDevice.isConnected).thenReturn(true)
- assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
+ )
.isFalse()
}
@@ -201,7 +236,9 @@
fun testSavedFactory_isFilterMatched_notBonded_returnsFalse() {
`when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_NONE)
- assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
+ )
.isFalse()
}
@@ -211,7 +248,9 @@
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(true)
- assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
+ )
.isFalse()
}
@@ -223,7 +262,9 @@
`when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
`when`(cachedDevice.isConnected).thenReturn(false)
- assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
+ )
.isTrue()
}
@@ -235,7 +276,9 @@
`when`(cachedDevice.bondState).thenReturn(BluetoothDevice.BOND_BONDED)
`when`(cachedDevice.isConnected).thenReturn(true)
- assertThat(savedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ savedDeviceItemFactory.isFilterMatched(context, cachedDevice, isOngoingCall = false)
+ )
.isFalse()
}
@@ -244,14 +287,26 @@
fun testConnectedFactory_isFilterMatched_bondedAndConnected_returnsTrue() {
`when`(BluetoothUtils.isConnectedBluetoothDevice(any(), any())).thenReturn(true)
- assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ connectedDeviceItemFactory.isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ )
+ )
.isTrue()
}
@Test
@DisableFlags(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
fun testConnectedFactory_isFilterMatched_notConnected_returnsFalse() {
- assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ connectedDeviceItemFactory.isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ )
+ )
.isFalse()
}
@@ -261,7 +316,13 @@
`when`(cachedDevice.device).thenReturn(bluetoothDevice)
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(true)
- assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ connectedDeviceItemFactory.isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ )
+ )
.isFalse()
}
@@ -272,7 +333,13 @@
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false)
`when`(BluetoothUtils.isConnectedBluetoothDevice(any(), any())).thenReturn(true)
- assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ connectedDeviceItemFactory.isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ )
+ )
.isTrue()
}
@@ -283,7 +350,13 @@
`when`(BluetoothUtils.isExclusivelyManagedBluetoothDevice(any(), any())).thenReturn(false)
`when`(BluetoothUtils.isConnectedBluetoothDevice(any(), any())).thenReturn(false)
- assertThat(connectedDeviceItemFactory.isFilterMatched(context, cachedDevice, audioManager))
+ assertThat(
+ connectedDeviceItemFactory.isFilterMatched(
+ context,
+ cachedDevice,
+ isOngoingCall = false,
+ )
+ )
.isFalse()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
index 42dc50d..943b89a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractorTest.kt
@@ -29,6 +29,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.testKosmos
import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.test.TestScope
@@ -102,7 +103,6 @@
DeviceItemInteractor(
bluetoothTileDialogRepository,
kosmos.audioSharingInteractor,
- audioManager,
adapter,
localBluetoothManager,
fakeSystemClock,
@@ -111,6 +111,7 @@
emptyList(),
testScope.backgroundScope,
dispatcher,
+ kosmos.audioModeInteractor,
)
val latest by collectLastValue(interactor.deviceItemUpdate)
@@ -130,7 +131,6 @@
DeviceItemInteractor(
bluetoothTileDialogRepository,
kosmos.audioSharingInteractor,
- audioManager,
adapter,
localBluetoothManager,
fakeSystemClock,
@@ -139,6 +139,7 @@
emptyList(),
testScope.backgroundScope,
dispatcher,
+ kosmos.audioModeInteractor,
)
val latest by collectLastValue(interactor.deviceItemUpdate)
@@ -158,7 +159,6 @@
DeviceItemInteractor(
bluetoothTileDialogRepository,
kosmos.audioSharingInteractor,
- audioManager,
adapter,
localBluetoothManager,
fakeSystemClock,
@@ -167,6 +167,7 @@
emptyList(),
testScope.backgroundScope,
dispatcher,
+ kosmos.audioModeInteractor,
)
val latest by collectLastValue(interactor.deviceItemUpdate)
@@ -186,7 +187,6 @@
DeviceItemInteractor(
bluetoothTileDialogRepository,
kosmos.audioSharingInteractor,
- audioManager,
adapter,
localBluetoothManager,
fakeSystemClock,
@@ -198,6 +198,7 @@
emptyList(),
testScope.backgroundScope,
dispatcher,
+ kosmos.audioModeInteractor,
)
val latest by collectLastValue(interactor.deviceItemUpdate)
@@ -217,7 +218,6 @@
DeviceItemInteractor(
bluetoothTileDialogRepository,
kosmos.audioSharingInteractor,
- audioManager,
adapter,
localBluetoothManager,
fakeSystemClock,
@@ -238,6 +238,7 @@
),
testScope.backgroundScope,
dispatcher,
+ kosmos.audioModeInteractor,
)
`when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
`when`(deviceItem2.type).thenReturn(DeviceItemType.SAVED_BLUETOOTH_DEVICE)
@@ -259,7 +260,6 @@
DeviceItemInteractor(
bluetoothTileDialogRepository,
kosmos.audioSharingInteractor,
- audioManager,
adapter,
localBluetoothManager,
fakeSystemClock,
@@ -277,6 +277,7 @@
listOf(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE),
testScope.backgroundScope,
dispatcher,
+ kosmos.audioModeInteractor,
)
`when`(deviceItem1.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
`when`(deviceItem2.type).thenReturn(DeviceItemType.CONNECTED_BLUETOOTH_DEVICE)
@@ -300,7 +301,6 @@
DeviceItemInteractor(
bluetoothTileDialogRepository,
kosmos.audioSharingInteractor,
- audioManager,
adapter,
localBluetoothManager,
fakeSystemClock,
@@ -309,6 +309,7 @@
emptyList(),
testScope.backgroundScope,
dispatcher,
+ kosmos.audioModeInteractor,
)
val latest by collectLastValue(interactor.deviceItemUpdate)
val latestShowSeeAll by collectLastValue(interactor.showSeeAllUpdate)
@@ -327,7 +328,7 @@
override fun isFilterMatched(
context: Context,
cachedDevice: CachedBluetoothDevice,
- audioManager: AudioManager,
+ isOngoingCall: Boolean,
audioSharingAvailable: Boolean,
) = isFilterMatchFunc(cachedDevice)
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d4bb1d5..258c955 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -812,7 +812,7 @@
handleMinimalPostProcessingAllowedSettingChange();
if (mFlags.isDisplayContentModeManagementEnabled()) {
- updateMirrorBuiltInDisplaySettingLocked();
+ updateMirrorBuiltInDisplaySettingLocked(/*shouldSendDisplayChangeEvent=*/ true);
}
final UserManager userManager = getUserManager();
@@ -868,7 +868,7 @@
updateHdrConversionModeSettingsLocked();
}
if (mFlags.isDisplayContentModeManagementEnabled()) {
- updateMirrorBuiltInDisplaySettingLocked();
+ updateMirrorBuiltInDisplaySettingLocked(/*shouldSendDisplayChangeEvent=*/ false);
}
}
@@ -1237,8 +1237,11 @@
}
if (Settings.Secure.getUriFor(MIRROR_BUILT_IN_DISPLAY).equals(uri)) {
- if (mFlags.isDisplayContentModeManagementEnabled()) {
- updateMirrorBuiltInDisplaySettingLocked();
+ synchronized (mSyncRoot) {
+ if (mFlags.isDisplayContentModeManagementEnabled()) {
+ updateMirrorBuiltInDisplaySettingLocked(/*shouldSendDisplayChangeEvent=*/
+ true);
+ }
}
return;
}
@@ -1258,18 +1261,19 @@
1, UserHandle.USER_CURRENT) != 0);
}
- private void updateMirrorBuiltInDisplaySettingLocked() {
- synchronized (mSyncRoot) {
- ContentResolver resolver = mContext.getContentResolver();
- final boolean mirrorBuiltInDisplay = Settings.Secure.getIntForUser(resolver,
- MIRROR_BUILT_IN_DISPLAY, 0, UserHandle.USER_CURRENT) != 0;
- if (mMirrorBuiltInDisplay == mirrorBuiltInDisplay) {
- return;
- }
- mMirrorBuiltInDisplay = mirrorBuiltInDisplay;
- if (mFlags.isDisplayContentModeManagementEnabled()) {
- mLogicalDisplayMapper.forEachLocked(this::updateCanHostTasksIfNeededLocked);
- }
+ private void updateMirrorBuiltInDisplaySettingLocked(boolean shouldSendDisplayChangeEvent) {
+ ContentResolver resolver = mContext.getContentResolver();
+ final boolean mirrorBuiltInDisplay = Settings.Secure.getIntForUser(resolver,
+ MIRROR_BUILT_IN_DISPLAY, 0, UserHandle.USER_CURRENT) != 0;
+ if (mMirrorBuiltInDisplay == mirrorBuiltInDisplay) {
+ return;
+ }
+ mMirrorBuiltInDisplay = mirrorBuiltInDisplay;
+ if (mFlags.isDisplayContentModeManagementEnabled()) {
+ mLogicalDisplayMapper.forEachLocked(logicalDisplay -> {
+ updateCanHostTasksIfNeededLocked(logicalDisplay,
+ shouldSendDisplayChangeEvent);
+ });
}
}
@@ -2380,7 +2384,7 @@
new BrightnessPair(brightnessDefault, brightnessDefault));
if (mFlags.isDisplayContentModeManagementEnabled()) {
- updateCanHostTasksIfNeededLocked(display);
+ updateCanHostTasksIfNeededLocked(display, /*shouldSendDisplayChangeEvent=*/ false);
}
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -2703,8 +2707,9 @@
}
}
- private void updateCanHostTasksIfNeededLocked(LogicalDisplay display) {
- if (display.setCanHostTasksLocked(!mMirrorBuiltInDisplay)) {
+ private void updateCanHostTasksIfNeededLocked(LogicalDisplay display,
+ boolean shouldSendDisplayChangeEvent) {
+ if (display.setCanHostTasksLocked(!mMirrorBuiltInDisplay) && shouldSendDisplayChangeEvent) {
sendDisplayEventIfEnabledLocked(display,
DisplayManagerGlobal.EVENT_DISPLAY_BASIC_CHANGED);
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 6cc17d4..a941838 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -857,8 +857,7 @@
info.mWindowsDrawnDelayMs = info.calculateDelay(timestampNs);
info.mIsDrawn = true;
final TransitionInfoSnapshot infoSnapshot = new TransitionInfoSnapshot(info);
- if (info.mLoggedTransitionStarting || (!r.mDisplayContent.mOpeningApps.contains(r)
- && !r.mTransitionController.isCollecting(r))) {
+ if (info.mLoggedTransitionStarting || !r.mTransitionController.isCollecting(r)) {
done(false /* abort */, info, "notifyWindowsDrawn", timestampNs);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c37b5a0..333d91a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -159,7 +159,6 @@
import static com.android.server.wm.ActivityRecordProto.IN_SIZE_COMPAT_MODE;
import static com.android.server.wm.ActivityRecordProto.IS_ANIMATING;
import static com.android.server.wm.ActivityRecordProto.IS_USER_FULLSCREEN_OVERRIDE_ENABLED;
-import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
import static com.android.server.wm.ActivityRecordProto.LAST_DROP_INPUT_MODE;
import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
@@ -330,7 +329,6 @@
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets;
-import android.view.WindowInsets.Type;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.TransitionOldType;
@@ -1519,17 +1517,7 @@
this.task = newTask;
if (shouldStartChangeTransition(newParent, oldParent)) {
- if (mTransitionController.isShellTransitionsEnabled()) {
- // For Shell transition, call #initializeChangeTransition directly to take the
- // screenshot at the Activity level. And Shell will be in charge of handling the
- // surface reparent and crop.
- initializeChangeTransition(getBounds());
- } else {
- // For legacy app transition, we want to take a screenshot of the Activity surface,
- // but animate the change transition on TaskFragment level to get the correct window
- // crop.
- newParent.initializeChangeTransition(getBounds(), getSurfaceControl());
- }
+ mTransitionController.collectVisibleChange(this);
}
super.onParentChanged(newParent, oldParent);
@@ -1557,16 +1545,6 @@
mLastReportedPictureInPictureMode = inPinnedWindowingMode();
}
- // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
- // access visual elements like the {@link DisplayContent}. We must remove any associations
- // such as animations.
- if (task == null) {
- // It is possible we have been marked as a closing app earlier. We must remove ourselves
- // from this list so we do not participate in any future animations.
- if (getDisplayContent() != null) {
- getDisplayContent().mClosingApps.remove(this);
- }
- }
final Task rootTask = getRootTask();
if (task == mLastParentBeforePip && task != null) {
// Notify the TaskFragmentOrganizer that the activity is reparented back from pip.
@@ -1749,14 +1727,6 @@
return;
}
prevDc.onRunningActivityChanged();
-
- if (prevDc.mOpeningApps.remove(this)) {
- // Transfer opening transition to new display.
- mDisplayContent.mOpeningApps.add(this);
- mDisplayContent.executeAppTransition();
- }
-
- prevDc.mClosingApps.remove(this);
prevDc.getDisplayPolicy().removeRelaunchingApp(this);
if (prevDc.mFocusedApp == this) {
@@ -4392,7 +4362,6 @@
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
- getDisplayContent().mOpeningApps.remove(this);
getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
mWmService.mSnapshotController.onAppRemoved(this);
mAtmService.mStartingProcessActivities.remove(this);
@@ -4404,20 +4373,9 @@
mAppCompatController.getTransparentPolicy().stop();
// Defer removal of this activity when either a child is animating, or app transition is on
- // going. App transition animation might be applied on the parent task not on the activity,
- // but the actual frame buffer is associated with the activity, so we have to keep the
- // activity while a parent is animating.
- boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN,
- ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION);
- if (getDisplayContent().mClosingApps.contains(this)) {
- delayed = true;
- } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
- getDisplayContent().mClosingApps.add(this);
- delayed = true;
- } else if (mTransitionController.inTransition()) {
- delayed = true;
- }
-
+ // going. The handleCompleteDeferredRemoval will continue the removal.
+ final boolean delayed = isAnimating(CHILDREN, ANIMATION_TYPE_WINDOW_ANIMATION)
+ || mTransitionController.inTransition();
// Don't commit visibility if it is waiting to animate. It will be set post animation.
if (!delayed) {
commitVisibility(false /* visible */, true /* performLayout */);
@@ -5552,9 +5510,6 @@
mAtmService.mBackNavigationController.onAppVisibilityChanged(this, visible);
- final DisplayContent displayContent = getDisplayContent();
- displayContent.mOpeningApps.remove(this);
- displayContent.mClosingApps.remove(this);
setVisibleRequested(visible);
mLastDeferHidingClient = deferHidingClient;
@@ -5567,13 +5522,6 @@
setClientVisible(false);
}
} else {
- if (!appTransition.isTransitionSet()
- && appTransition.isReady()) {
- // Add the app mOpeningApps if transition is unset but ready. This means
- // we're doing a screen freeze, and the unfreeze will wait for all opening
- // apps to be ready.
- displayContent.mOpeningApps.add(this);
- }
startingMoved = false;
// If the token is currently hidden (should be the common case), or has been
// stopped, then we need to set up to wait for its windows to be ready.
@@ -6775,7 +6723,7 @@
setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
// We can now show all of the drawn windows!
- if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
+ if (canShowWindows()) {
showAllWindowsLocked();
}
}
@@ -7449,15 +7397,6 @@
return boundsLayer;
}
- @Override
- boolean isWaitingForTransitionStart() {
- final DisplayContent dc = getDisplayContent();
- return dc != null && dc.mAppTransition.isTransitionSet()
- && (dc.mOpeningApps.contains(this)
- || dc.mClosingApps.contains(this)
- || dc.mChangingContainers.contains(this));
- }
-
boolean isTransitionForward() {
return (mStartingData != null && mStartingData.mIsTransitionForward)
|| mDisplayContent.isNextTransitionForward();
@@ -9561,7 +9500,6 @@
writeNameToProto(proto, NAME);
super.dumpDebug(proto, WINDOW_TOKEN, logLevel);
proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
- proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
proto.write(IS_ANIMATING, isAnimating(TRANSITION | PARENTS | CHILDREN,
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION));
proto.write(FILLS_PARENT, fillsParent());
diff --git a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
index dff072e..57811e2 100644
--- a/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java
@@ -16,12 +16,14 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.window.DesktopModeFlags.EXCLUDE_CAPTION_FROM_APP_BOUNDS;
import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
import static com.android.server.wm.AppCompatConfiguration.letterboxBackgroundTypeToString;
@@ -48,6 +50,8 @@
*/
class AppCompatLetterboxPolicy {
+ private static final int DIFF_TOLERANCE_PX = 1;
+
@NonNull
private final ActivityRecord mActivityRecord;
@NonNull
@@ -56,6 +60,9 @@
private final AppCompatRoundedCorners mAppCompatRoundedCorners;
@NonNull
private final AppCompatConfiguration mAppCompatConfiguration;
+ // Convenience temporary object to save allocation when calculating Rect.
+ @NonNull
+ private final Rect mTmpRect = new Rect();
private boolean mLastShouldShowLetterboxUi;
@@ -71,7 +78,7 @@
: new LegacyLetterboxPolicyState();
// TODO (b/358334569) Improve cutout logic dependency on app compat.
mAppCompatRoundedCorners = new AppCompatRoundedCorners(mActivityRecord,
- this::isLetterboxedNotForDisplayCutout);
+ this::ieEligibleForRoundedCorners);
mAppCompatConfiguration = appCompatConfiguration;
}
@@ -84,7 +91,7 @@
mLetterboxPolicyState.stop();
}
- /** @return {@value true} if the letterbox policy is running and the activity letterboxed. */
+ /** @return {@code true} if the letterbox policy is running and the activity letterboxed. */
boolean isRunning() {
return mLetterboxPolicyState.isRunning();
}
@@ -130,7 +137,7 @@
* <li>The activity is in fullscreen.
* <li>The activity is portrait-only.
* <li>The activity doesn't have a starting window (education should only be displayed
- * once the starting window is removed in {@link #removeStartingWindow}).
+ * once the starting window is removed in {@link ActivityRecord#removeStartingWindow}).
* </ul>
*/
boolean isEligibleForLetterboxEducation() {
@@ -294,16 +301,40 @@
}
}
+ private boolean ieEligibleForRoundedCorners(@NonNull WindowState mainWindow) {
+ return isLetterboxedNotForDisplayCutout(mainWindow)
+ && !isFreeformActivityMatchParentAppBoundsHeight();
+ }
+
private boolean isLetterboxedNotForDisplayCutout(@NonNull WindowState mainWindow) {
return shouldShowLetterboxUi(mainWindow)
&& !mainWindow.isLetterboxedForDisplayCutout();
}
+ private boolean isFreeformActivityMatchParentAppBoundsHeight() {
+ if (!EXCLUDE_CAPTION_FROM_APP_BOUNDS.isTrue()) {
+ return false;
+ }
+ final Task task = mActivityRecord.getTask();
+ if (task == null) {
+ return false;
+ }
+ final Rect parentAppBounds = task.getWindowConfiguration().getAppBounds();
+ if (parentAppBounds == null) {
+ return false;
+ }
+
+ mLetterboxPolicyState.getLetterboxInnerBounds(mTmpRect);
+ final int diff = parentAppBounds.height() - mTmpRect.height();
+ // Compare bounds with tolerance of 1 px to account for rounding error calculations.
+ return task.getWindowingMode() == WINDOWING_MODE_FREEFORM && diff <= DIFF_TOLERANCE_PX;
+ }
+
private static boolean shouldNotLayoutLetterbox(@Nullable WindowState w) {
if (w == null) {
return true;
}
- final int type = w.mAttrs.type;
+ final int type = w.getAttrs().type;
// Allow letterbox to be displayed early for base application or application starting
// windows even if it is not on the top z order to prevent flickering when the
// letterboxed window is brought to the top
diff --git a/services/core/java/com/android/server/wm/AppCompatRoundedCorners.java b/services/core/java/com/android/server/wm/AppCompatRoundedCorners.java
index 92d76e5..8165638 100644
--- a/services/core/java/com/android/server/wm/AppCompatRoundedCorners.java
+++ b/services/core/java/com/android/server/wm/AppCompatRoundedCorners.java
@@ -35,12 +35,12 @@
@NonNull
private final ActivityRecord mActivityRecord;
@NonNull
- private final Predicate<WindowState> mIsLetterboxedNotForDisplayCutout;
+ private final Predicate<WindowState> mRoundedCornersWindowCondition;
AppCompatRoundedCorners(@NonNull ActivityRecord activityRecord,
- @NonNull Predicate<WindowState> isLetterboxedNotForDisplayCutout) {
+ @NonNull Predicate<WindowState> roundedCornersWindowCondition) {
mActivityRecord = activityRecord;
- mIsLetterboxedNotForDisplayCutout = isLetterboxedNotForDisplayCutout;
+ mRoundedCornersWindowCondition = roundedCornersWindowCondition;
}
void updateRoundedCornersIfNeeded(@NonNull final WindowState mainWindow) {
@@ -136,7 +136,7 @@
private boolean requiresRoundedCorners(@NonNull final WindowState mainWindow) {
final AppCompatLetterboxOverrides letterboxOverrides = mActivityRecord
.mAppCompatController.getLetterboxOverrides();
- return mIsLetterboxedNotForDisplayCutout.test(mainWindow)
+ return mRoundedCornersWindowCondition.test(mainWindow)
&& letterboxOverrides.isLetterboxActivityCornersRounded();
}
diff --git a/services/core/java/com/android/server/wm/AppCompatSandboxingPolicy.java b/services/core/java/com/android/server/wm/AppCompatSandboxingPolicy.java
index 26cf32b..6a46f57 100644
--- a/services/core/java/com/android/server/wm/AppCompatSandboxingPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatSandboxingPolicy.java
@@ -15,6 +15,8 @@
*/
package com.android.server.wm;
+import static android.window.DesktopModeFlags.EXCLUDE_CAPTION_FROM_APP_BOUNDS;
+
import static com.android.server.wm.AppCompatUtils.isInDesktopMode;
import android.annotation.NonNull;
@@ -22,8 +24,6 @@
import android.content.res.Configuration;
import android.graphics.Rect;
-import com.android.window.flags.Flags;
-
/**
* Encapsulate logic related to sandboxing for app compatibility.
*/
@@ -48,7 +48,7 @@
*/
void sandboxBoundsIfNeeded(@NonNull Configuration resolvedConfig,
@WindowingMode int windowingMode) {
- if (!Flags.excludeCaptionFromAppBounds()) {
+ if (!EXCLUDE_CAPTION_FROM_APP_BOUNDS.isTrue()) {
return;
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index d98ad8b..12d4a21 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -89,7 +89,6 @@
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ANIM;
-import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS;
import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE;
import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION;
@@ -1554,26 +1553,6 @@
}
private void handleAppTransitionTimeout() {
- synchronized (mService.mGlobalLock) {
- final DisplayContent dc = mDisplayContent;
- if (dc == null) {
- return;
- }
- notifyAppTransitionTimeoutLocked();
- if (isTransitionSet() || !dc.mOpeningApps.isEmpty() || !dc.mClosingApps.isEmpty()
- || !dc.mChangingContainers.isEmpty()) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "*** APP TRANSITION TIMEOUT. displayId=%d isTransitionSet()=%b "
- + "mOpeningApps.size()=%d mClosingApps.size()=%d "
- + "mChangingApps.size()=%d",
- dc.getDisplayId(), dc.mAppTransition.isTransitionSet(),
- dc.mOpeningApps.size(), dc.mClosingApps.size(),
- dc.mChangingContainers.size());
-
- setTimeout();
- mService.mWindowPlacerLocked.performSurfacePlacement();
- }
- }
}
private static void doAnimationCallback(@NonNull IRemoteCallback callback) {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 05dcbb7..aaa18ad 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -257,10 +257,12 @@
// This should be the only place override the configuration for ActivityRecord. Override
// the value if not calculated yet.
Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
+ Rect outConfigBounds = new Rect(outAppBounds);
if (outAppBounds == null || outAppBounds.isEmpty()) {
inOutConfig.windowConfiguration.setAppBounds(
newParentConfiguration.windowConfiguration.getBounds());
outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
+ outConfigBounds.set(outAppBounds);
if (task != null) {
task = task.getCreatedByOrganizerTask();
if (task != null && (task.mOffsetYForInsets != 0 || task.mOffsetXForInsets != 0)) {
@@ -279,6 +281,12 @@
outAppBounds.inset(decor.mOverrideNonDecorInsets);
}
}
+ if (!outConfigBounds.intersect(decor.mOverrideConfigFrame)) {
+ if (inOutConfig.windowConfiguration.getWindowingMode()
+ == WINDOWING_MODE_MULTI_WINDOW) {
+ outAppBounds.inset(decor.mOverrideConfigInsets);
+ }
+ }
if (task != null && (task.mOffsetYForInsets != 0 || task.mOffsetXForInsets != 0)) {
outAppBounds.offset(-task.mOffsetXForInsets, -task.mOffsetYForInsets);
}
@@ -289,10 +297,10 @@
}
density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
- inOutConfig.screenWidthDp = (int) (outAppBounds.width() / density + 0.5f);
+ inOutConfig.screenWidthDp = (int) (outConfigBounds.width() / density + 0.5f);
}
if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
- inOutConfig.screenHeightDp = (int) (outAppBounds.height() / density + 0.5f);
+ inOutConfig.screenHeightDp = (int) (outConfigBounds.height() / density + 0.5f);
}
if (inOutConfig.smallestScreenWidthDp == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
&& parentWindowingMode == WINDOWING_MODE_FULLSCREEN) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 703ce7d..7eebbba 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -108,7 +108,6 @@
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY;
import static com.android.server.wm.DisplayContentProto.APP_TRANSITION;
-import static com.android.server.wm.DisplayContentProto.CLOSING_APPS;
import static com.android.server.wm.DisplayContentProto.CURRENT_FOCUS;
import static com.android.server.wm.DisplayContentProto.DISPLAY_FRAMES;
import static com.android.server.wm.DisplayContentProto.DISPLAY_INFO;
@@ -125,7 +124,6 @@
import static com.android.server.wm.DisplayContentProto.IS_SLEEPING;
import static com.android.server.wm.DisplayContentProto.KEEP_CLEAR_AREAS;
import static com.android.server.wm.DisplayContentProto.MIN_SIZE_OF_RESIZEABLE_TASK_DP;
-import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayContentProto.SLEEP_TOKENS;
@@ -164,6 +162,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
+import android.content.ComponentCallbacks;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -196,7 +195,6 @@
import android.os.UserManager;
import android.os.WorkSource;
import android.provider.Settings;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.DisplayUtils;
@@ -367,15 +365,7 @@
final AppTransition mAppTransition;
- final ArraySet<ActivityRecord> mOpeningApps = new ArraySet<>();
- final ArraySet<ActivityRecord> mClosingApps = new ArraySet<>();
- final ArraySet<WindowContainer> mChangingContainers = new ArraySet<>();
final UnknownAppVisibilityController mUnknownAppVisibilityController;
- /**
- * If a container is closing when resizing, keeps track of its starting bounds when it is
- * removed from {@link #mChangingContainers}.
- */
- final ArrayMap<WindowContainer, Rect> mClosingChangingContainers = new ArrayMap<>();
private MetricsLogger mMetricsLogger;
@@ -467,6 +457,7 @@
private DisplayInfo mLastDisplayInfoOverride;
private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+ @NonNull
private final DisplayPolicy mDisplayPolicy;
private final DisplayRotation mDisplayRotation;
@@ -553,6 +544,7 @@
/** Remove this display when animation on it has completed. */
private boolean mDeferredRemoval;
+ @NonNull
final PinnedTaskController mPinnedTaskController;
private final LinkedList<ActivityRecord> mTmpUpdateAllDrawn = new LinkedList();
@@ -1113,6 +1105,29 @@
};
/**
+ * Called to update fields retrieve from {@link #getDisplayUiContext()} resources when
+ * there's a configuration update on {@link #getDisplayUiContext()}.
+ */
+ @NonNull
+ private final ComponentCallbacks mSysUiContextConfigCallback = new ComponentCallbacks() {
+
+ @Override
+ public void onConfigurationChanged(@NonNull Configuration newConfig) {
+ synchronized (mWmService.mGlobalLock) {
+ if (mDisplayReady) {
+ mDisplayPolicy.onConfigurationChanged();
+ mMinSizeOfResizeableTaskDp = getMinimalTaskSizeDp();
+ }
+ }
+ }
+
+ @Override
+ public void onLowMemory() {
+ // Do nothing.
+ }
+ };
+
+ /**
* Create new {@link DisplayContent} instance, add itself to the root window container and
* initialize direct children.
* @param display May not be null.
@@ -1910,17 +1925,10 @@
return false;
}
if (checkOpening) {
- if (mTransitionController.isShellTransitionsEnabled()) {
- if (!mTransitionController.isCollecting(r)) {
- return false;
- }
- } else {
- if (!mAppTransition.isTransitionSet() || !mOpeningApps.contains(r)) {
- // Apply normal rotation animation in case of the activity set different
- // requested orientation without activity switch, or the transition is unset due
- // to starting window was transferred ({@link #mSkipAppTransitionAnimation}).
- return false;
- }
+ if (!mTransitionController.isCollecting(r)) {
+ // Apply normal rotation animation in case the activity changes requested
+ // orientation without activity switch.
+ return false;
}
if (r.isState(RESUMED) && !r.getTask().mInResumeTopActivity) {
// If the activity is executing or has done the lifecycle callback, use normal
@@ -2815,11 +2823,10 @@
final int lastOrientation = getConfiguration().orientation;
final int lastWindowingMode = getWindowingMode();
super.onConfigurationChanged(newParentConfig);
- if (mDisplayPolicy != null) {
- mDisplayPolicy.onConfigurationChanged();
- mPinnedTaskController.onPostDisplayConfigurationChanged();
- mMinSizeOfResizeableTaskDp = getMinimalTaskSizeDp();
+ if (!Flags.trackSystemUiContextBeforeWms()) {
+ mSysUiContextConfigCallback.onConfigurationChanged(newParentConfig);
}
+ mPinnedTaskController.onPostDisplayConfigurationChanged();
// Update IME parent if needed.
updateImeParent();
@@ -3256,7 +3263,12 @@
}
}
- private boolean allowContentModeSwitch() {
+ /**
+ * Note that we only allow displays that are able to show system decorations to use the content
+ * mode switch; however, not all displays that are able to show system decorations are allowed
+ * to use the content mode switch.
+ */
+ boolean allowContentModeSwitch() {
// The default display should always show system decorations.
if (isDefaultDisplay) {
return false;
@@ -3372,10 +3384,6 @@
void removeImmediately() {
mDeferredRemoval = false;
try {
- // Clear all transitions & screen frozen states when removing display.
- mOpeningApps.clear();
- mClosingApps.clear();
- mChangingContainers.clear();
mUnknownAppVisibilityController.clear();
mAppTransition.removeAppTransitionTimeoutCallbacks();
mTransitionController.unregisterLegacyListener(mFixedRotationTransitionListener);
@@ -3398,6 +3406,9 @@
.getKeyguardController().onDisplayRemoved(mDisplayId);
mWallpaperController.resetLargestDisplay(mDisplay);
mWmService.mDisplayWindowSettings.onDisplayRemoved(this);
+ if (Flags.trackSystemUiContextBeforeWms()) {
+ getDisplayUiContext().unregisterComponentCallbacks(mSysUiContextConfigCallback);
+ }
} finally {
mDisplayReady = false;
}
@@ -3567,12 +3578,6 @@
if (mFocusedApp != null) {
mFocusedApp.writeNameToProto(proto, FOCUSED_APP);
}
- for (int i = mOpeningApps.size() - 1; i >= 0; i--) {
- mOpeningApps.valueAt(i).writeIdentifierToProto(proto, OPENING_APPS);
- }
- for (int i = mClosingApps.size() - 1; i >= 0; i--) {
- mClosingApps.valueAt(i).writeIdentifierToProto(proto, CLOSING_APPS);
- }
final Task focusedRootTask = getFocusedRootTask();
if (focusedRootTask != null) {
@@ -4831,19 +4836,6 @@
}
}
- if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty() || !mChangingContainers.isEmpty()) {
- pw.println();
- if (mOpeningApps.size() > 0) {
- pw.print(" mOpeningApps="); pw.println(mOpeningApps);
- }
- if (mClosingApps.size() > 0) {
- pw.print(" mClosingApps="); pw.println(mClosingApps);
- }
- if (mChangingContainers.size() > 0) {
- pw.print(" mChangingApps="); pw.println(mChangingContainers);
- }
- }
-
mUnknownAppVisibilityController.dump(pw, " ");
}
@@ -5465,7 +5457,7 @@
reconfigureDisplayLocked();
onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
mWmService.mDisplayNotificationController.dispatchDisplayAdded(this);
- // Attach the SystemUiContext to this DisplayContent the get latest configuration.
+ // Attach the SystemUiContext to this DisplayContent to get latest configuration.
// Note that the SystemUiContext will be removed automatically if this DisplayContent
// is detached.
registerSystemUiContext();
@@ -5473,11 +5465,15 @@
}
private void registerSystemUiContext() {
+ final Context systemUiContext = getDisplayUiContext();
final WindowProcessController wpc = mAtmService.getProcessController(
- getDisplayUiContext().getIApplicationThread());
+ systemUiContext.getIApplicationThread());
mWmService.mWindowContextListenerController.registerWindowContainerListener(
- wpc, getDisplayUiContext().getWindowContextToken(), this,
+ wpc, systemUiContext.getWindowContextToken(), this,
INVALID_WINDOW_TYPE, null /* options */);
+ if (Flags.trackSystemUiContextBeforeWms()) {
+ systemUiContext.registerComponentCallbacks(mSysUiContextConfigCallback);
+ }
}
@Override
@@ -6656,6 +6652,7 @@
forAllTasks((t) -> { t.getRootTask().removeChild(t, "removeAllTasks"); });
}
+ @NonNull
Context getDisplayUiContext() {
return mDisplayPolicy.getSystemUiContext();
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 10f591c..fbe8501 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1865,6 +1865,7 @@
return mContext;
}
+ @NonNull
Context getSystemUiContext() {
return mUiContext;
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 539fc12..1173875 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -247,12 +247,7 @@
void setShouldShowSystemDecorsLocked(@NonNull DisplayContent dc, boolean shouldShow) {
final boolean changed = (shouldShow != shouldShowSystemDecorsLocked(dc));
-
- final DisplayInfo displayInfo = dc.getDisplayInfo();
- final SettingsProvider.SettingsEntry overrideSettings =
- mSettingsProvider.getOverrideSettings(displayInfo);
- overrideSettings.mShouldShowSystemDecors = shouldShow;
- mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
+ setShouldShowSystemDecorsInternalLocked(dc, shouldShow);
if (enableDisplayContentModeManagement()) {
if (dc.isDefaultDisplay || dc.isPrivate() || !changed) {
@@ -269,6 +264,15 @@
}
}
+ void setShouldShowSystemDecorsInternalLocked(@NonNull DisplayContent dc,
+ boolean shouldShow) {
+ final DisplayInfo displayInfo = dc.getDisplayInfo();
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mShouldShowSystemDecors = shouldShow;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
+ }
+
boolean isHomeSupportedLocked(@NonNull DisplayContent dc) {
if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
// Default display should show home.
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index c93efd3..40f16c1 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2775,6 +2775,12 @@
return;
}
+ if (enableDisplayContentModeManagement() && display.allowContentModeSwitch()) {
+ mWindowManager.mDisplayWindowSettings
+ .setShouldShowSystemDecorsInternalLocked(display,
+ display.mDisplay.canHostTasks());
+ }
+
startSystemDecorations(display, "displayAdded");
// Drop any cached DisplayInfos associated with this display id - the values are now
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bf9883c76..6b3499a 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2028,7 +2028,7 @@
}
if (shouldStartChangeTransition(prevWinMode, mTmpPrevBounds)) {
- initializeChangeTransition(mTmpPrevBounds);
+ mTransitionController.collectVisibleChange(this);
}
// If the configuration supports persistent bounds (eg. Freeform), keep track of the
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 74059c1..a698a9e 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2779,9 +2779,7 @@
}
// If this TaskFragment is closing while resizing, crop to the starting bounds instead.
- final Rect bounds = isClosingWhenResizing()
- ? mDisplayContent.mClosingChangingContainers.get(this)
- : getBounds();
+ final Rect bounds = getBounds();
final int width = bounds.width();
final int height = bounds.height();
if (!forceUpdate && width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index c1ef208..a8b9fed 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -292,12 +292,6 @@
return false;
}
- boolean isWallpaperTargetAnimating() {
- return mWallpaperTarget != null && mWallpaperTarget.isAnimating(TRANSITION | PARENTS)
- && (mWallpaperTarget.mActivityRecord == null
- || !mWallpaperTarget.mActivityRecord.isWaitingForTransitionStart());
- }
-
void hideDeferredWallpapersIfNeededLegacy() {
for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
final WallpaperWindowToken token = mWallpaperTokens.get(i);
@@ -837,14 +831,6 @@
// Use the old target if new target is hidden but old target
// is not. If they're both hidden, still use the new target.
mWallpaperTarget = prevWallpaperTarget;
- } else if (newTargetHidden == oldTargetHidden
- && !mDisplayContent.mOpeningApps.contains(wallpaperTarget.mActivityRecord)
- && (mDisplayContent.mOpeningApps.contains(prevWallpaperTarget.mActivityRecord)
- || mDisplayContent.mClosingApps.contains(prevWallpaperTarget.mActivityRecord))) {
- // If they're both hidden (or both not hidden), prefer the one that's currently in
- // opening or closing app list, this allows transition selection logic to better
- // determine the wallpaper status of opening/closing apps.
- mWallpaperTarget = prevWallpaperTarget;
}
result.setWallpaperTarget(wallpaperTarget);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 95cdf46..45202a2 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -34,7 +34,6 @@
import static android.view.SurfaceControl.Transaction;
import static android.view.WindowInsets.Type.InsetsType;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
-import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.window.TaskFragmentAnimationParams.DEFAULT_ANIMATION_BACKGROUND_COLOR;
import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION;
@@ -901,10 +900,6 @@
*/
@CallSuper
void removeImmediately() {
- final DisplayContent dc = getDisplayContent();
- if (dc != null) {
- dc.mClosingChangingContainers.remove(this);
- }
while (!mChildren.isEmpty()) {
final E child = mChildren.getLast();
child.removeImmediately();
@@ -1116,10 +1111,6 @@
if (asWindowState() == null) {
mTransitionController.collect(this);
}
- // Cancel any change transition queued-up for this container on the old display when
- // this container is moved from the old display.
- mDisplayContent.mClosingChangingContainers.remove(this);
- mDisplayContent.mChangingContainers.remove(this);
}
mDisplayContent = dc;
if (dc != null && dc != this && mPendingTransaction != null) {
@@ -1268,14 +1259,6 @@
}
/**
- * @return {@code true} when the container is waiting the app transition start, {@code false}
- * otherwise.
- */
- boolean isWaitingForTransitionStart() {
- return false;
- }
-
- /**
* @return {@code true} if in this subtree of the hierarchy we have an
* {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
*/
@@ -1302,13 +1285,6 @@
return isAnimating(0 /* self only */);
}
- /**
- * @return {@code true} if the container is in changing app transition.
- */
- boolean isChangingAppTransition() {
- return mDisplayContent != null && mDisplayContent.mChangingContainers.contains(this);
- }
-
boolean inTransition() {
return mTransitionController.inTransition(this);
}
@@ -1427,12 +1403,6 @@
return setVisibleRequested(newVisReq);
}
- /** Whether this window is closing while resizing. */
- boolean isClosingWhenResizing() {
- return mDisplayContent != null
- && mDisplayContent.mClosingChangingContainers.containsKey(this);
- }
-
void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(HASH_CODE, System.identityHashCode(this));
@@ -3044,36 +3014,6 @@
|| (getParent() != null && getParent().inPinnedWindowingMode());
}
- /**
- * Initializes a change transition.
- *
- * For now, this will only be called for the following cases:
- * 1. {@link Task} is changing windowing mode between fullscreen and freeform.
- * 2. {@link TaskFragment} is organized and is changing window bounds.
- * 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}. (The
- * transition will happen on the {@link TaskFragment} for this case).
- *
- * This shouldn't be called on other {@link WindowContainer} unless there is a valid
- * use case.
- *
- * @param startBounds The original bounds (on screen) of the surface we are snapshotting.
- */
- void initializeChangeTransition(Rect startBounds, @Nullable SurfaceControl freezeTarget) {
- if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) {
- mDisplayContent.mTransitionController.collectVisibleChange(this);
- return;
- }
- mDisplayContent.prepareAppTransition(TRANSIT_CHANGE);
- mDisplayContent.mChangingContainers.add(this);
- // Calculate the relative position in parent container.
- final Rect parentBounds = getParent().getBounds();
- mTmpPoint.set(startBounds.left - parentBounds.left, startBounds.top - parentBounds.top);
- }
-
- void initializeChangeTransition(Rect startBounds) {
- initializeChangeTransition(startBounds, null /* freezeTarget */);
- }
-
ArraySet<WindowContainer> getAnimationSources() {
return mSurfaceAnimationSources;
}
@@ -3166,8 +3106,7 @@
getAnimationPosition(mTmpPoint);
mTmpRect.offsetTo(0, 0);
- final boolean isChanging = AppTransition.isChangeTransitOld(transit) && enter
- && isChangingAppTransition();
+ final boolean isChanging = AppTransition.isChangeTransitOld(transit);
if (isChanging) {
final float durationScale = mWmService.getTransitionAnimationScaleLocked();
@@ -3519,9 +3458,6 @@
&& (mSurfaceAnimator.getAnimationType() & typesToCheck) > 0) {
return true;
}
- if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
- return true;
- }
return false;
}
@@ -3603,13 +3539,7 @@
return;
}
- if (isClosingWhenResizing()) {
- // This container is closing while resizing, keep its surface at the starting position
- // to prevent animation flicker.
- getRelativePosition(mDisplayContent.mClosingChangingContainers.get(this), mTmpPos);
- } else {
- getRelativePosition(mTmpPos);
- }
+ getRelativePosition(mTmpPos);
final int deltaRotation = getRelativeDisplayRotation();
if (mTmpPos.equals(mLastSurfacePosition) && deltaRotation == mLastDeltaRotation) {
return;
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 4c53ba5..4b4736e 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -1060,7 +1060,7 @@
effects |= applyChanges(taskFragment, c);
if (taskFragment.shouldStartChangeTransition(mTmpBounds0, mTmpBounds1)) {
- taskFragment.initializeChangeTransition(mTmpBounds0);
+ mTransitionController.collectVisibleChange(taskFragment);
}
taskFragment.continueOrganizedTaskFragmentSurfaceUpdate();
return effects;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5897241..9f1289b2 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3272,13 +3272,6 @@
mDestroying = false;
destroyedSomething = true;
}
-
- // Since mDestroying will affect ActivityRecord#allDrawn, we need to perform another
- // traversal in case we are waiting on this window to start the transition.
- if (getDisplayContent().mAppTransition.isTransitionSet()
- && getDisplayContent().mOpeningApps.contains(mActivityRecord)) {
- mWmService.mWindowPlacerLocked.requestTraversal();
- }
}
return destroyedSomething;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 9e7575f..f5bda9f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -104,7 +104,6 @@
.setTask(mTrampolineActivity.getTask())
.setComponent(createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, "TopActivity"))
.build();
- mTopActivity.mDisplayContent.mOpeningApps.add(mTopActivity);
mTransition = new Transition(TRANSIT_OPEN, 0 /* flags */,
mTopActivity.mTransitionController, createTestBLASTSyncEngine());
mTransition.mParticipants.add(mTopActivity);
@@ -485,7 +484,6 @@
@Test
public void testActivityDrawnWithoutTransition() {
- mTopActivity.mDisplayContent.mOpeningApps.remove(mTopActivity);
mTransition.mParticipants.remove(mTopActivity);
onIntentStarted(mTopActivity.intent);
notifyAndVerifyActivityLaunched(mTopActivity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index bb29614..280e432 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -3326,16 +3326,13 @@
makeWindowVisibleAndDrawn(app);
// Put the activity in close transition.
- mDisplayContent.mOpeningApps.clear();
- mDisplayContent.mClosingApps.add(app.mActivityRecord);
- mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
+ requestTransition(app.mActivityRecord, WindowManager.TRANSIT_CLOSE);
// Remove window during transition, so it is requested to hide, but won't be committed until
// the transition is finished.
app.mActivityRecord.onRemovedFromDisplay();
app.mActivityRecord.prepareSurfaces();
- assertTrue(mDisplayContent.mClosingApps.contains(app.mActivityRecord));
assertFalse(app.mActivityRecord.isVisibleRequested());
assertTrue(app.mActivityRecord.isVisible());
assertTrue(app.mActivityRecord.isSurfaceShowing());
@@ -3353,11 +3350,6 @@
makeWindowVisibleAndDrawn(app);
app.mActivityRecord.prepareSurfaces();
- // Put the activity in close transition.
- mDisplayContent.mOpeningApps.clear();
- mDisplayContent.mClosingApps.add(app.mActivityRecord);
- mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
-
// Commit visibility before start transition.
app.mActivityRecord.commitVisibility(false, false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
index 018ea58..d016e735 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
@@ -151,6 +151,10 @@
doReturn(taskBounds).when(mTaskStack.top()).getBounds();
}
+ void configureTaskAppBounds(@NonNull Rect appBounds) {
+ mTaskStack.top().getWindowConfiguration().setAppBounds(appBounds);
+ }
+
void configureTopActivityBounds(@NonNull Rect activityBounds) {
doReturn(activityBounds).when(mActivityStack.top()).getBounds();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatLetterboxPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatLetterboxPolicyTest.java
index 0c31032..2603d78 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatLetterboxPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatLetterboxPolicyTest.java
@@ -16,7 +16,9 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
@@ -27,6 +29,7 @@
import static org.mockito.Mockito.mock;
import android.graphics.Rect;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -40,6 +43,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.R;
+import com.android.window.flags.Flags;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -225,6 +229,53 @@
});
}
+ @Test
+ @EnableFlags(Flags.FLAG_EXCLUDE_CAPTION_FROM_APP_BOUNDS)
+ public void testGetRoundedCornersRadius_letterboxBoundsMatchHeightInFreeform_notRounded() {
+ runTestScenario((robot) -> {
+ robot.conf().setLetterboxActivityCornersRadius(15);
+ robot.configureWindowState();
+ robot.activity().createActivityWithComponent();
+ robot.setTopActivityInLetterboxAnimation(/* inLetterboxAnimation */ false);
+ robot.activity().setTopActivityVisible(/* isVisible */ true);
+ robot.setIsLetterboxedForFixedOrientationAndAspectRatio(/* inLetterbox */ true);
+ robot.conf().setLetterboxActivityCornersRounded(/* rounded */ true);
+ robot.resources().configureGetDimensionPixelSize(R.dimen.taskbar_frame_height, 20);
+
+ robot.activity().setTaskWindowingMode(WINDOWING_MODE_FREEFORM);
+ final Rect appBounds = new Rect(0, 0, 100, 500);
+ robot.configureWindowStateFrame(appBounds);
+ robot.activity().configureTaskAppBounds(appBounds);
+
+ robot.startLetterbox();
+
+ robot.checkWindowStateRoundedCornersRadius(/* expected */ 0);
+ });
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EXCLUDE_CAPTION_FROM_APP_BOUNDS)
+ public void testGetRoundedCornersRadius_letterboxBoundsNotMatchHeightInFreeform_rounded() {
+ runTestScenario((robot) -> {
+ robot.conf().setLetterboxActivityCornersRadius(15);
+ robot.configureWindowState();
+ robot.activity().createActivityWithComponent();
+ robot.setTopActivityInLetterboxAnimation(/* inLetterboxAnimation */ false);
+ robot.activity().setTopActivityVisible(/* isVisible */ true);
+ robot.setIsLetterboxedForFixedOrientationAndAspectRatio(/* inLetterbox */ true);
+ robot.conf().setLetterboxActivityCornersRounded(/* rounded */ true);
+ robot.resources().configureGetDimensionPixelSize(R.dimen.taskbar_frame_height, 20);
+
+ robot.activity().setTaskWindowingMode(WINDOWING_MODE_FREEFORM);
+ robot.configureWindowStateFrame(new Rect(0, 0, 500, 200));
+ robot.activity().configureTaskAppBounds(new Rect(0, 0, 500, 500));
+
+ robot.startLetterbox();
+
+ robot.checkWindowStateRoundedCornersRadius(/* expected */ 15);
+ });
+ }
+
/**
* Runs a test scenario providing a Robot.
*/
@@ -265,6 +316,10 @@
spyOn(getTransparentPolicy());
}
+ void startLetterbox() {
+ getAppCompatLetterboxPolicy().start(mWindowState);
+ }
+
void configureWindowStateWithTaskBar(boolean hasInsetsRoundedCorners) {
configureWindowState(/* withTaskBar */ true, hasInsetsRoundedCorners);
}
@@ -273,6 +328,10 @@
configureWindowState(/* withTaskBar */ false, /* hasInsetsRoundedCorners */ false);
}
+ void configureWindowStateFrame(@NonNull Rect frame) {
+ doReturn(frame).when(mWindowState).getFrame();
+ }
+
void configureInsetsRoundedCorners(@NonNull RoundedCorners roundedCorners) {
mInsetsState.setRoundedCorners(roundedCorners);
}
@@ -290,6 +349,7 @@
}
mWindowState.mInvGlobalScale = 1f;
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
+ attrs.type = TYPE_BASE_APPLICATION;
doReturn(mInsetsState).when(mWindowState).getInsetsState();
doReturn(attrs).when(mWindowState).getAttrs();
doReturn(true).when(mWindowState).isDrawn();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 6e109a8..d5b9751 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1800,8 +1800,7 @@
final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
app.setVisible(false);
app.setState(ActivityRecord.State.RESUMED, "test");
- mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_OPEN);
- mDisplayContent.mOpeningApps.add(app);
+ requestTransition(app, WindowManager.TRANSIT_OPEN);
final int newOrientation = getRotatedOrientation(mDisplayContent);
app.setRequestedOrientation(newOrientation);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 7ab55bf..cc2a76d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -189,11 +189,12 @@
doReturn(true).when(mTaskFragment).isVisible();
doReturn(true).when(mTaskFragment).isVisibleRequested();
+ spyOn(mTaskFragment.mTransitionController);
clearInvocations(mTransaction);
mTaskFragment.setBounds(endBounds);
// No change transition, but update the organized surface position.
- verify(mTaskFragment, never()).initializeChangeTransition(any(), any());
+ verify(mTaskFragment.mTransitionController, never()).collectVisibleChange(any());
verify(mTransaction).setPosition(mLeash, endBounds.left, endBounds.top);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index edffab8..cee98fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -409,17 +409,6 @@
}
@Test
- public void testIsAnimating_TransitionFlag() {
- final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
- final TestWindowContainer root = builder.setLayer(0).build();
- final TestWindowContainer child1 = root.addChildWindow(
- builder.setWaitForTransitionStart(true));
-
- assertFalse(root.isAnimating(TRANSITION));
- assertTrue(child1.isAnimating(TRANSITION));
- }
-
- @Test
public void testIsAnimating_ParentsFlag() {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
final TestWindowContainer root = builder.setLayer(0).build();
@@ -1655,7 +1644,7 @@
};
TestWindowContainer(WindowManagerService wm, int layer, boolean isAnimating,
- boolean isVisible, boolean waitTransitStart, Integer orientation, WindowState ws) {
+ boolean isVisible, Integer orientation, WindowState ws) {
super(wm);
mLayer = layer;
@@ -1663,7 +1652,6 @@
mIsVisible = isVisible;
mFillsParent = true;
mOrientation = orientation;
- mWaitForTransitStart = waitTransitStart;
mWindowState = ws;
spyOn(mSurfaceAnimator);
doReturn(mIsAnimating).when(mSurfaceAnimator).isAnimating();
@@ -1729,11 +1717,6 @@
}
@Override
- boolean isWaitingForTransitionStart() {
- return mWaitForTransitStart;
- }
-
- @Override
WindowState asWindowState() {
return mWindowState;
}
@@ -1744,7 +1727,6 @@
private int mLayer;
private boolean mIsAnimating;
private boolean mIsVisible;
- private boolean mIsWaitTransitStart;
private Integer mOrientation;
private WindowState mWindowState;
@@ -1782,14 +1764,9 @@
return this;
}
- TestWindowContainerBuilder setWaitForTransitionStart(boolean waitTransitStart) {
- mIsWaitTransitStart = waitTransitStart;
- return this;
- }
-
TestWindowContainer build() {
return new TestWindowContainer(mWm, mLayer, mIsAnimating, mIsVisible,
- mIsWaitTransitStart, mOrientation, mWindowState);
+ mOrientation, mWindowState);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 1dfb20a..d228970 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION;
import static android.content.res.Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -33,9 +34,11 @@
import static com.android.server.wm.ActivityRecord.State.STARTED;
import static com.android.server.wm.ActivityRecord.State.STOPPED;
import static com.android.server.wm.ActivityRecord.State.STOPPING;
+import static com.android.server.wm.ConfigurationContainer.applySizeOverrideIfNeeded;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -58,6 +61,7 @@
import android.graphics.Rect;
import android.os.LocaleList;
import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import org.junit.Before;
@@ -453,6 +457,56 @@
assertEquals(topDisplayArea, mWpc.getTopActivityDisplayArea());
}
+ @Test
+ @EnableFlags(com.android.window.flags.Flags.FLAG_INSETS_DECOUPLED_CONFIGURATION)
+ public void testOverrideConfigurationApplied() {
+ final DisplayContent displayContent = new TestDisplayContent.Builder(mAtm, 1000, 1500)
+ .setSystemDecorations(true).setDensityDpi(160).build();
+ final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
+ // Setup the decor insets info.
+ final DisplayPolicy.DecorInsets.Info decorInsetsInfo = new DisplayPolicy.DecorInsets.Info();
+ final Rect emptyRect = new Rect();
+ decorInsetsInfo.mNonDecorInsets.set(emptyRect);
+ decorInsetsInfo.mConfigInsets.set(emptyRect);
+ decorInsetsInfo.mOverrideConfigInsets.set(new Rect(0, 100, 0, 200));
+ decorInsetsInfo.mOverrideNonDecorInsets.set(new Rect(0, 0, 0, 200));
+ decorInsetsInfo.mNonDecorFrame.set(new Rect(0, 0, 1000, 1500));
+ decorInsetsInfo.mConfigFrame.set(new Rect(0, 0, 1000, 1500));
+ decorInsetsInfo.mOverrideConfigFrame.set(new Rect(0, 100, 1000, 1300));
+ decorInsetsInfo.mOverrideNonDecorFrame.set(new Rect(0, 0, 1000, 1300));
+ doReturn(decorInsetsInfo).when(displayPolicy)
+ .getDecorInsetsInfo(anyInt(), anyInt(), anyInt());
+
+ final Configuration newParentConfig = displayContent.getConfiguration();
+ final Configuration resolvedConfig = new Configuration();
+
+ // Mock the app info to not enforce the decoupled configuration to apply the override.
+ final ApplicationInfo appInfo = mock(ApplicationInfo.class);
+ doReturn(false).when(appInfo)
+ .isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED);
+ doReturn(false).when(appInfo)
+ .isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION);
+
+ // No value should be set before override.
+ assertNull(resolvedConfig.windowConfiguration.getAppBounds());
+ applySizeOverrideIfNeeded(
+ displayContent,
+ appInfo,
+ newParentConfig,
+ resolvedConfig,
+ false /* optsOutEdgeToEdge */,
+ false /* hasFixedRotationTransform */,
+ false /* hasCompatDisplayInsets */,
+ null /* task */);
+
+ // Assert the override config insets are applied.
+ // Status bars, and all non-decor insets should be deducted for the config screen size.
+ assertEquals(1200, resolvedConfig.screenHeightDp);
+ // Only the non-decor insets should be deducted for the app bounds.
+ assertNotNull(resolvedConfig.windowConfiguration.getAppBounds());
+ assertEquals(1300, resolvedConfig.windowConfiguration.getAppBounds().height());
+ }
+
private TestDisplayContent createTestDisplayContentInContainer() {
return new TestDisplayContent.Builder(mAtm, 1000, 1500).build();
}