Merge cherrypicks of ['googleplex-android-review.googlesource.com/26621463', 'googleplex-android-review.googlesource.com/26681774', 'googleplex-android-review.googlesource.com/26741740', 'googleplex-android-review.googlesource.com/26837538', 'googleplex-android-review.googlesource.com/26875227', 'googleplex-android-review.googlesource.com/26905538', 'googleplex-android-review.googlesource.com/27015418'] into 24Q2-release.
Change-Id: I1853d6149b716bba6624a0cea2cba63f91b7dbdb
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 828004b..0ced3a6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8430,8 +8430,9 @@
* hierarchy
* @param refocus when propagate is true, specifies whether to request the
* root view place new focus
+ * @hide
*/
- void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
+ public void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
mPrivateFlags &= ~PFLAG_FOCUSED;
clearParentsWantFocus();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1721462..92dcf88 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9733,7 +9733,7 @@
return KEY_EVENT_HANDLED;
}
if (hasFocus()) {
- clearFocus();
+ clearFocusInternal(null, /* propagate */ true, /* refocus */ false);
InputMethodManager imm = getInputMethodManager();
if (imm != null) {
imm.hideSoftInputFromView(this, 0);
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1d03301..ad864ec 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -994,7 +994,15 @@
}
void CanvasContext::onContextDestroyed() {
- destroyHardwareResources();
+ // We don't want to destroyHardwareResources as that will invalidate display lists which
+ // the client may not be expecting. Instead just purge all scratch resources
+ if (mRenderPipeline->isContextReady()) {
+ freePrefetchedLayers();
+ for (const sp<RenderNode>& node : mRenderNodes) {
+ node->destroyLayers();
+ }
+ mRenderPipeline->onDestroyHardwareResources();
+ }
}
DeferredLayerUpdater* CanvasContext::createTextureLayer() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index b3b7bce..fd08daf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -1188,9 +1188,7 @@
}
boolean isVolumeControlEnabled(@NonNull MediaDevice device) {
- return (isPlayBackInfoLocal()
- || device.getDeviceType() != MediaDevice.MediaDeviceType.TYPE_CAST_GROUP_DEVICE)
- && !device.isVolumeFixed();
+ return !device.isVolumeFixed();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index dfe41eb..592df5e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -35,6 +35,7 @@
import android.content.ContentResolver;
import android.content.Context;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
@@ -73,6 +74,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import dagger.Lazy;
@@ -100,7 +102,7 @@
AccessibilityButtonModeObserver.ModeChangedListener,
AccessibilityButtonTargetsObserver.TargetsChangedListener,
OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
- Dumpable, CommandQueue.Callbacks {
+ Dumpable, CommandQueue.Callbacks, ConfigurationController.ConfigurationListener {
private static final String TAG = NavBarHelper.class.getSimpleName();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -188,6 +190,7 @@
UserTracker userTracker,
DisplayTracker displayTracker,
NotificationShadeWindowController notificationShadeWindowController,
+ ConfigurationController configurationController,
DumpManager dumpManager,
CommandQueue commandQueue,
@Main Executor mainExecutor) {
@@ -214,6 +217,7 @@
mNavBarMode = navigationModeController.addListener(this);
mCommandQueue.addCallback(this);
+ configurationController.addCallback(this);
overviewProxyService.addCallback(this);
dumpManager.registerDumpable(this);
}
@@ -358,6 +362,11 @@
updateA11yState();
}
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ mEdgeBackGestureHandler.onConfigurationChanged(newConfig);
+ }
+
/**
* Updates the current accessibility button state. The accessibility button state is only
* used for {@link Secure#ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR} and
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 1793861..13ba9c3 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -874,11 +874,6 @@
refreshLayout(ld);
}
repositionNavigationBar(rotation);
- // NOTE(b/260220098): In some cases, the recreated nav bar will already have the right
- // configuration, which means that NavBarView will not receive a configuration change to
- // propagate to EdgeBackGestureHandler (which is injected into this and NBV). As such, we
- // should also force-update the gesture handler to ensure it updates to the right bounds
- mEdgeBackGestureHandler.onConfigurationChanged(newConfig);
if (canShowSecondaryHandle()) {
if (rotation != mCurrentRotation) {
mCurrentRotation = rotation;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
index 152f193..42a25bd 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
@@ -160,14 +160,11 @@
mIsLargeScreen = isLargeScreen(mContext);
boolean willApplyConfig = mConfigChanges.applyNewConfig(mContext.getResources());
boolean largeScreenChanged = mIsLargeScreen != isOldConfigLargeScreen;
- // TODO(b/243765256): Disable this logging once b/243765256 is fixed.
+ // TODO(b/332635834): Disable this logging once b/332635834 is fixed.
Log.i(DEBUG_MISSING_GESTURE_TAG, "NavbarController: newConfig=" + newConfig
+ " mTaskbarDelegate initialized=" + mTaskbarDelegate.isInitialized()
+ " willApplyConfigToNavbars=" + willApplyConfig
+ " navBarCount=" + mNavigationBars.size());
- if (mTaskbarDelegate.isInitialized()) {
- mTaskbarDelegate.onConfigurationChanged(newConfig);
- }
// If we folded/unfolded while in 3 button, show navbar in folded state, hide in unfolded
if (largeScreenChanged && updateNavbarForTaskbar()) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index c5190a2..bc0a1da 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -1026,7 +1026,6 @@
updateIcons(mTmpLastConfiguration);
updateRecentsIcon();
updateCurrentRotation();
- mEdgeBackGestureHandler.onConfigurationChanged(mConfiguration);
if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi
|| mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) {
// If car mode or density changes, we need to reset the icons.
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index 5dd1bd8..f67973b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -39,7 +39,6 @@
import android.app.StatusBarManager;
import android.app.StatusBarManager.WindowVisibleState;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
@@ -72,7 +71,6 @@
import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -250,8 +248,6 @@
mLightBarController.setNavigationBar(mLightBarTransitionsController);
mPipOptional.ifPresent(this::addPipExclusionBoundsChangeListener);
mEdgeBackGestureHandler.setBackAnimation(mBackAnimation);
- mEdgeBackGestureHandler.onConfigurationChanged(
- mContext.getResources().getConfiguration());
mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
mInitialized = true;
} finally {
@@ -495,10 +491,6 @@
return mBehavior != BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
}
- public void onConfigurationChanged(Configuration configuration) {
- mEdgeBackGestureHandler.onConfigurationChanged(configuration);
- }
-
@Override
public void setNavigationBarLumaSamplingEnabled(int displayId, boolean enable) {
mOverviewProxyService.onNavigationBarLumaSamplingEnabled(displayId, enable);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 91c86df..d40949f 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -1180,7 +1180,7 @@
updateDisabledForQuickstep(newConfig);
}
- // TODO(b/243765256): Disable this logging once b/243765256 is fixed.
+ // TODO(b/332635834): Disable this logging once b/332635834 is fixed.
Log.i(DEBUG_MISSING_GESTURE_TAG, "Config changed: newConfig=" + newConfig
+ " lastReportedConfig=" + mLastReportedConfig);
mLastReportedConfig.updateFrom(newConfig);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
index e5ba569..277119d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -35,6 +35,7 @@
import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.content.res.Configuration;
import android.view.IWindowManager;
import android.view.accessibility.AccessibilityManager;
@@ -54,6 +55,8 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.FakeConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
@@ -116,6 +119,7 @@
EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
@Mock
NotificationShadeWindowController mNotificationShadeWindowController;
+ ConfigurationController mConfigurationController = new FakeConfigurationController();
private AccessibilityManager.AccessibilityServicesStateChangeListener
mAccessibilityServicesStateChangeListener;
@@ -143,9 +147,8 @@
mSystemActions, mOverviewProxyService, mAssistManagerLazy,
() -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class),
mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker,
- mDisplayTracker, mNotificationShadeWindowController, mDumpManager, mCommandQueue,
- mSynchronousExecutor);
-
+ mDisplayTracker, mNotificationShadeWindowController, mConfigurationController,
+ mDumpManager, mCommandQueue, mSynchronousExecutor);
}
@Test
@@ -334,6 +337,12 @@
assertThat(state2.mWindowState).isNotEqualTo(newState);
}
+ @Test
+ public void configUpdatePropagatesToEdgeBackGestureHandler() {
+ mConfigurationController.onConfigurationChanged(Configuration.EMPTY);
+ verify(mEdgeBackGestureHandler, times(1)).onConfigurationChanged(any());
+ }
+
private List<String> createFakeShortcutTargets() {
return new ArrayList<>(List.of("a", "b", "c", "d"));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
index 52859cd..df75ea7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerImplTest.java
@@ -37,11 +37,8 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import android.content.res.Configuration;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.util.SparseArray;
@@ -292,23 +289,6 @@
}
@Test
- public void testConfigurationChange_taskbarNotInitialized() {
- Configuration configuration = mContext.getResources().getConfiguration();
- mNavigationBarController.mIsLargeScreen = true;
- mNavigationBarController.onConfigChanged(configuration);
- verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
- }
-
- @Test
- public void testConfigurationChange_taskbarInitialized() {
- Configuration configuration = mContext.getResources().getConfiguration();
- mNavigationBarController.mIsLargeScreen = true;
- when(mTaskbarDelegate.isInitialized()).thenReturn(true);
- mNavigationBarController.onConfigChanged(configuration);
- verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
- }
-
- @Test
public void testShouldRenderTaskbar_taskbarNotRenderedOnPhone() {
mNavigationBarController.mIsLargeScreen = false;
mNavigationBarController.mIsPhone = true;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 31746a2..2382746 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -110,6 +110,7 @@
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.DeviceConfigProxyFake;
@@ -274,8 +275,8 @@
mKeyguardStateController, mock(NavigationModeController.class),
mEdgeBackGestureHandlerFactory, mock(IWindowManager.class),
mock(UserTracker.class), mock(DisplayTracker.class),
- mNotificationShadeWindowController, mock(DumpManager.class),
- mock(CommandQueue.class), mSynchronousExecutor));
+ mNotificationShadeWindowController, mock(ConfigurationController.class),
+ mock(DumpManager.class), mock(CommandQueue.class), mSynchronousExecutor));
mNavigationBar = createNavBar(mContext);
mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
});
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 663ba8a..7f5a865 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4451,7 +4451,9 @@
}
}
- if (packageName == null || uninstalling || packageStateStopped) {
+ final boolean clearPendingIntentsForStoppedApp = (android.content.pm.Flags.stayStopped()
+ && packageStateStopped);
+ if (packageName == null || uninstalling || clearPendingIntentsForStoppedApp) {
didSomething |= mPendingIntentController.removePendingIntentsForPackage(
packageName, userId, appId, doit);
}
diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
index 1715254..9d04682 100644
--- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
+++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java
@@ -196,8 +196,7 @@
File signatureFile = new File(dir, FONT_SIGNATURE_FILE);
if (!signatureFile.exists()) {
Slog.i(TAG, "The signature file is missing.");
- FileUtils.deleteContentsAndDir(dir);
- continue;
+ return;
}
byte[] signature;
try {
@@ -222,10 +221,36 @@
FontFileInfo fontFileInfo = validateFontFile(fontFile, signature);
if (fontConfig == null) {
- fontConfig = getSystemFontConfig();
+ // Use preinstalled font config for checking revision number.
+ fontConfig = mConfigSupplier.apply(Collections.emptyMap());
}
addFileToMapIfSameOrNewer(fontFileInfo, fontConfig, true /* deleteOldFile */);
}
+
+ // Treat as error if post script name of font family was not installed.
+ for (int i = 0; i < config.fontFamilies.size(); ++i) {
+ FontUpdateRequest.Family family = config.fontFamilies.get(i);
+ for (int j = 0; j < family.getFonts().size(); ++j) {
+ FontUpdateRequest.Font font = family.getFonts().get(j);
+ if (mFontFileInfoMap.containsKey(font.getPostScriptName())) {
+ continue;
+ }
+
+ if (fontConfig == null) {
+ fontConfig = mConfigSupplier.apply(Collections.emptyMap());
+ }
+
+ if (getFontByPostScriptName(font.getPostScriptName(), fontConfig) != null) {
+ continue;
+ }
+
+ Slog.e(TAG, "Unknown font that has PostScript name "
+ + font.getPostScriptName() + " is requested in FontFamily "
+ + family.getName());
+ return;
+ }
+ }
+
success = true;
} catch (Throwable t) {
// If something happened during loading system fonts, clear all contents in finally
@@ -237,6 +262,7 @@
mFontFileInfoMap.clear();
mLastModifiedMillis = 0;
FileUtils.deleteContents(mFilesDir);
+ mConfigFile.delete();
}
}
}
@@ -485,8 +511,7 @@
return shouldAddToMap;
}
- private long getPreinstalledFontRevision(FontFileInfo info, FontConfig fontConfig) {
- String psName = info.getPostScriptName();
+ private FontConfig.Font getFontByPostScriptName(String psName, FontConfig fontConfig) {
FontConfig.Font targetFont = null;
for (int i = 0; i < fontConfig.getFontFamilies().size(); i++) {
FontConfig.FontFamily family = fontConfig.getFontFamilies().get(i);
@@ -511,6 +536,13 @@
}
}
}
+ return targetFont;
+ }
+
+ private long getPreinstalledFontRevision(FontFileInfo info, FontConfig fontConfig) {
+ String psName = info.getPostScriptName();
+ FontConfig.Font targetFont = getFontByPostScriptName(psName, fontConfig);
+
if (targetFont == null) {
return -1;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1353ff0..2212724 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5770,7 +5770,7 @@
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (isTopRootTaskInDisplayArea() && mAtmService.mController != null) {
+ if (mAtmService.mController != null && isTopRootTaskInDisplayArea()) {
ActivityRecord next = topRunningActivity(null, task.mTaskId);
if (next == null) {
next = topRunningActivity(null, INVALID_TASK_ID);
@@ -5814,6 +5814,15 @@
+ tr.mTaskId);
if (mTransitionController.isShellTransitionsEnabled()) {
+ // TODO(b/277838915): Consider to make it concurrent to eliminate the special case.
+ final Transition collecting = mTransitionController.getCollectingTransition();
+ if (collecting != null && collecting.mType == TRANSIT_OPEN) {
+ // It can be a CLOSING participate of an OPEN transition. This avoids the deferred
+ // transition from moving task to back after the task was moved to front.
+ collecting.collect(tr);
+ moveTaskToBackInner(tr, collecting);
+ return true;
+ }
final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */,
mTransitionController, mWmService.mSyncEngine);
// Guarantee that this gets its own transition by queueing on SyncEngine
@@ -5842,7 +5851,7 @@
return true;
}
- private boolean moveTaskToBackInner(@NonNull Task task, @Nullable Transition transition) {
+ private void moveTaskToBackInner(@NonNull Task task, @Nullable Transition transition) {
final Transition.ReadyCondition movedToBack =
new Transition.ReadyCondition("moved-to-back", task);
if (transition != null) {
@@ -5857,7 +5866,7 @@
if (inPinnedWindowingMode()) {
mTaskSupervisor.removeRootTask(this);
- return true;
+ return;
}
mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
@@ -5880,7 +5889,6 @@
} else {
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
- return true;
}
boolean willActivityBeVisible(IBinder token) {
diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
index dacff4c..fa89278 100644
--- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
+++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java
@@ -999,6 +999,563 @@
assertThat(mUpdatableFontFilesDir.list()).hasLength(0);
}
+ private UpdatableFontDir createNewUpdateDir() {
+ UpdatableFontDir dir = new UpdatableFontDir(
+ mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
+ mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
+ dir.loadFontFileMap();
+ return dir;
+ }
+
+ private UpdatableFontDir installTestFontFamilies(int version) {
+ UpdatableFontDir dir = createNewUpdateDir();
+ try {
+ dir.update(Arrays.asList(
+ newFontUpdateRequest("foo.ttf," + version + ",foo", GOOD_SIGNATURE),
+ newFontUpdateRequest("bar.ttf," + version + ",bar", GOOD_SIGNATURE),
+ newAddFontFamilyRequest("<family name='foobar'>"
+ + " <font>foo.ttf</font>"
+ + " <font>bar.ttf</font>"
+ + "</family>")));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return dir;
+ }
+
+ private UpdatableFontDir installTestFontFile(int numFonts, int version) {
+ UpdatableFontDir dir = createNewUpdateDir();
+ List<FontUpdateRequest> requests = new ArrayList<>();
+ if (numFonts <= 0 || numFonts > 3) {
+ throw new IllegalArgumentException("numFont must be 1, 2 or 3");
+ }
+ try {
+ requests.add(newFontUpdateRequest("foo.ttf," + version + ",foo", GOOD_SIGNATURE));
+ if (numFonts >= 2) {
+ requests.add(newFontUpdateRequest("bar.ttf," + version + ",bar", GOOD_SIGNATURE));
+ }
+ if (numFonts == 3) {
+ requests.add(newFontUpdateRequest("baz.ttf," + version + ",baz", GOOD_SIGNATURE));
+ }
+ dir.update(requests);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return dir;
+ }
+
+ private List<File> collectSignatureFiles() {
+ return Arrays.stream(mUpdatableFontFilesDir.listFiles())
+ .map((file) -> file.listFiles((unused, s) -> s.endsWith(".fsv_sig")))
+ .flatMap(Arrays::stream)
+ .toList();
+ }
+
+ private List<File> collectFontFiles() {
+ return Arrays.stream(mUpdatableFontFilesDir.listFiles())
+ .map((file) -> file.listFiles((unused, s) -> s.endsWith(".ttf")))
+ .flatMap(Arrays::stream)
+ .toList();
+ }
+
+ private void removeAll(List<File> files) {
+ files.forEach((File file) -> {
+ if (file.isDirectory()) {
+ removeAll(List.of(file.listFiles()));
+ } else {
+ assertThat(file.delete()).isTrue();
+ }
+ });
+ }
+
+ private void assertTestFontFamilyInstalled(UpdatableFontDir dir, int version) {
+ try {
+ assertNamedFamilyExists(dir.getSystemFontConfig(), "foobar");
+ assertThat(dir.getFontFamilyMap()).containsKey("foobar");
+ assertThat(dir.getFontFamilyMap().get("foobar").getFamilies().size()).isEqualTo(1);
+ FontConfig.FontFamily foobar = dir.getFontFamilyMap().get("foobar").getFamilies()
+ .get(0);
+ assertThat(foobar.getFontList()).hasSize(2);
+ assertThat(foobar.getFontList().get(0).getFile())
+ .isEqualTo(dir.getPostScriptMap().get("foo"));
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(version);
+ assertThat(foobar.getFontList().get(1).getFile())
+ .isEqualTo(dir.getPostScriptMap().get("bar"));
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(version);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void assertTestFontInstalled(UpdatableFontDir dir, int version) {
+ try {
+ assertThat(dir.getPostScriptMap().containsKey("foo")).isTrue();
+ assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(version);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void signatureMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one signature file
+ assertThat(collectSignatureFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(2 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void signatureAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all signature files
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf and bar.ttf
+ installTestFontFile(2 /* numFonts */, 1 /* version */);
+
+ // Delete one font file
+ assertThat(collectFontFiles().get(0).delete()).isTrue();
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(2 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void fontDirAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(List.of(mUpdatableFontFilesDir.listFiles()));
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFamilyInstalled_fontFamilyInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFamilyInstalled_fontInstallLater() {
+ // Install font families, foo.ttf, bar.ttf.
+ installTestFontFamilies(1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFileInstalled_fontFamilyInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFamilies(2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontFamilyInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontFamilyInstalled(nextDir, 2 /* version */);
+ }
+
+ @Test
+ public void dirContentAllMissingCase_fontFileInstalled_fontFileInstallLater() {
+ // Install font file, foo.ttf
+ installTestFontFile(1 /* numFonts */, 1 /* version */);
+
+ // Delete all font files
+ removeAll(collectFontFiles());
+ removeAll(collectSignatureFiles());
+
+ // New instance of UpdatableFontDir, this emulate a device reboot.
+ UpdatableFontDir dir = installTestFontFile(1 /* numFonts */, 2 /* version */);
+
+ // Make sure the font installation succeeds.
+ assertTestFontInstalled(dir, 2 /* version */);
+
+ // Make sure after the reboot, the configuration remains.
+ UpdatableFontDir nextDir = createNewUpdateDir();
+ assertTestFontInstalled(nextDir, 2 /* version */);
+ }
+
private FontUpdateRequest newFontUpdateRequest(String content, String signature)
throws Exception {
File file = File.createTempFile("font", "ttf", mCacheDir);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index ce890f6..9657eb2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -64,8 +64,10 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -2367,9 +2369,7 @@
assertTrue(transitA.isCollecting());
// finish collecting A
- transitA.start();
- transitA.setAllReady();
- mSyncEngine.tryFinishForTest(transitA.getSyncId());
+ tryFinishTransitionSyncSet(transitA);
waitUntilHandlersIdle();
assertTrue(transitA.isPlaying());
@@ -2475,6 +2475,36 @@
}
@Test
+ public void testDeferredMoveTaskToBack() {
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final Task task = activity.getTask();
+ registerTestTransitionPlayer();
+ final TransitionController controller = mWm.mRoot.mTransitionController;
+ mSyncEngine = createTestBLASTSyncEngine();
+ controller.setSyncEngine(mSyncEngine);
+ final Transition transition = createTestTransition(TRANSIT_CHANGE, controller);
+ controller.moveToCollecting(transition);
+ task.moveTaskToBack(task);
+ // Actual action will be deferred by current transition.
+ verify(task, never()).moveToBack(any(), any());
+
+ tryFinishTransitionSyncSet(transition);
+ waitUntilHandlersIdle();
+ // Continue to move task to back after the transition is done.
+ verify(task).moveToBack(any(), any());
+ final Transition moveBackTransition = controller.getCollectingTransition();
+ assertNotNull(moveBackTransition);
+ moveBackTransition.abort();
+
+ // The move-to-back can be collected in to a collecting OPEN transition.
+ clearInvocations(task);
+ final Transition transition2 = createTestTransition(TRANSIT_OPEN, controller);
+ controller.moveToCollecting(transition2);
+ task.moveTaskToBack(task);
+ verify(task).moveToBack(any(), any());
+ }
+
+ @Test
public void testNoSyncFlagIfOneTrack() {
final TransitionController controller = mAtm.getTransitionController();
final TestTransitionPlayer player = registerTestTransitionPlayer();
@@ -2491,17 +2521,11 @@
controller.startCollectOrQueue(transitC, (deferred) -> {});
// Verify that, as-long as there is <= 1 track, we won't get a SYNC flag
- transitA.start();
- transitA.setAllReady();
- mSyncEngine.tryFinishForTest(transitA.getSyncId());
+ tryFinishTransitionSyncSet(transitA);
assertTrue((player.mLastReady.getFlags() & FLAG_SYNC) == 0);
- transitB.start();
- transitB.setAllReady();
- mSyncEngine.tryFinishForTest(transitB.getSyncId());
+ tryFinishTransitionSyncSet(transitB);
assertTrue((player.mLastReady.getFlags() & FLAG_SYNC) == 0);
- transitC.start();
- transitC.setAllReady();
- mSyncEngine.tryFinishForTest(transitC.getSyncId());
+ tryFinishTransitionSyncSet(transitC);
assertTrue((player.mLastReady.getFlags() & FLAG_SYNC) == 0);
}
@@ -2610,6 +2634,12 @@
assertEquals("reason1", condition1.mAlternate);
}
+ private void tryFinishTransitionSyncSet(Transition transition) {
+ transition.setAllReady();
+ transition.start();
+ mSyncEngine.tryFinishForTest(transition.getSyncId());
+ }
+
private static void makeTaskOrganized(Task... tasks) {
final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
for (Task t : tasks) {