From 12e3f1f2f7e4af4ac534038df440413f97259ef7 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 15 Jul 2021 14:31:58 -0700 Subject: [PATCH] Removing UI dependency from LauncherModel in case of 2-panel layout Bug: 175939730 Bug: 192431856 Bug: 185515153 Test: Manual Change-Id: I8baa1cf9e5a8a04d5b8bc38c1f4b0755265cd8a9 --- .../WidgetsPredicationUpdateTaskTest.java | 9 - .../model/ModelMultiCallbacksTest.java | 3 +- .../util/LauncherPageRestoreHelperTest.java | 224 ------------------ .../android/launcher3/DeleteDropTarget.java | 15 +- src/com/android/launcher3/Launcher.java | 79 ++++-- .../launcher3/LauncherPageRestoreHelper.java | 92 ------- .../android/launcher3/LauncherProvider.java | 3 +- src/com/android/launcher3/Workspace.java | 51 +--- .../graphics/PreviewSurfaceRenderer.java | 1 - .../model/AddWorkspaceItemsTask.java | 17 +- .../launcher3/model/BaseLoaderResults.java | 24 +- .../android/launcher3/model/BgDataModel.java | 18 +- .../android/launcher3/model/LoaderTask.java | 16 +- .../android/launcher3/model/ModelWriter.java | 7 - 14 files changed, 110 insertions(+), 449 deletions(-) delete mode 100644 robolectric_tests/src/com/android/launcher3/util/LauncherPageRestoreHelperTest.java delete mode 100644 src/com/android/launcher3/LauncherPageRestoreHelper.java diff --git a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java index 1386ac0371..f82fbcc15b 100644 --- a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java +++ b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java @@ -34,7 +34,6 @@ import android.content.Context; import android.os.Process; import android.os.UserHandle; -import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.ComponentWithLabel; @@ -42,7 +41,6 @@ import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.QuickstepModelDelegate.PredictorState; import com.android.launcher3.shadows.ShadowDeviceFlag; -import com.android.launcher3.util.IntSet; import com.android.launcher3.util.LauncherModelHelper; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.PendingAddWidgetInfo; @@ -76,7 +74,6 @@ public final class WidgetsPredicationUpdateTaskTest { private Context mContext; private LauncherModelHelper mModelHelper; private UserHandle mUserHandle; - private InvariantDeviceProfile mTestProfile; @Mock private IconCache mIconCache; @@ -92,7 +89,6 @@ public final class WidgetsPredicationUpdateTaskTest { mContext = RuntimeEnvironment.application; mModelHelper = new LauncherModelHelper(); mUserHandle = Process.myUserHandle(); - mTestProfile = new InvariantDeviceProfile(); // 2 widgets, app4/provider1 & app5/provider1, have already been added to the workspace. mModelHelper.initializeData("/widgets_predication_update_task_data.txt"); @@ -226,10 +222,5 @@ public final class WidgetsPredicationUpdateTaskTest { public void bindExtraContainerItems(FixedContainerItems item) { mRecommendedWidgets = item; } - - @Override - public IntSet getPagesToBindSynchronously() { - return IntSet.wrap(0); - } } } diff --git a/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java b/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java index 07351fe65b..43193553fe 100644 --- a/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java +++ b/robolectric_tests/src/com/android/launcher3/model/ModelMultiCallbacksTest.java @@ -31,6 +31,7 @@ import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.shadows.ShadowLooperExecutor; import com.android.launcher3.util.Executors; +import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.LauncherLayoutBuilder; import com.android.launcher3.util.LauncherModelHelper; @@ -202,7 +203,7 @@ public class ModelMultiCallbacksTest { } @Override - public IntSet getPagesToBindSynchronously() { + public IntSet getPagesToBindSynchronously(IntArray orderedScreenIds) { return mPageToBindSync; } diff --git a/robolectric_tests/src/com/android/launcher3/util/LauncherPageRestoreHelperTest.java b/robolectric_tests/src/com/android/launcher3/util/LauncherPageRestoreHelperTest.java deleted file mode 100644 index 51f5851823..0000000000 --- a/robolectric_tests/src/com/android/launcher3/util/LauncherPageRestoreHelperTest.java +++ /dev/null @@ -1,224 +0,0 @@ -/** - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.launcher3.util; - -import android.os.Bundle; - -import com.android.launcher3.LauncherPageRestoreHelper; -import com.android.launcher3.Workspace; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.when; - -@RunWith(RobolectricTestRunner.class) -public class LauncherPageRestoreHelperTest { - - // Type: int - private static final String RUNTIME_STATE_CURRENT_SCREEN = "launcher.current_screen"; - // Type: int - private static final String RUNTIME_STATE_CURRENT_SCREEN_COUNT = - "launcher.current_screen_count"; - - private LauncherPageRestoreHelper mPageRestoreHelper; - private Bundle mState; - - @Mock - private Workspace mWorkspace; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mPageRestoreHelper = new LauncherPageRestoreHelper(mWorkspace); - mState = new Bundle(); - } - - @Test - public void givenNoChildrenInWorkspace_whenSavePages_thenNothingSaved() { - when(mWorkspace.getChildCount()).thenReturn(0); - - mPageRestoreHelper.savePagesToRestore(mState); - - assertFalse(mState.containsKey(RUNTIME_STATE_CURRENT_SCREEN_COUNT)); - assertFalse(mState.containsKey(RUNTIME_STATE_CURRENT_SCREEN)); - } - - @Test - public void givenMultipleCurrentPages_whenSavePages_thenSavedCorrectly() { - when(mWorkspace.getChildCount()).thenReturn(5); - when(mWorkspace.getCurrentPage()).thenReturn(2); - givenPanelCount(2); - - mPageRestoreHelper.savePagesToRestore(mState); - - assertEquals(5, mState.getInt(RUNTIME_STATE_CURRENT_SCREEN_COUNT)); - assertEquals(2, mState.getInt(RUNTIME_STATE_CURRENT_SCREEN)); - } - - @Test - public void givenNullSavedState_whenRestorePages_thenReturnEmptyIntSet() { - IntSet result = mPageRestoreHelper.getPagesToRestore(null); - - assertTrue(result.isEmpty()); - } - - @Test - public void givenTotalPageCountMissing_whenRestorePages_thenReturnEmptyIntSet() { - givenSavedCurrentPage(1); - givenPanelCount(1); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertTrue(result.isEmpty()); - } - - @Test - public void givenCurrentPageMissing_whenRestorePages_thenReturnEmptyIntSet() { - givenSavedPageCount(3); - givenPanelCount(2); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertTrue(result.isEmpty()); - } - - @Test - public void givenOnePanel_whenRestorePages_thenReturnThatPage() { - givenSavedCurrentPage(2); - givenSavedPageCount(5); - givenPanelCount(1); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(1, result.size()); - assertEquals(2, result.getArray().get(0)); - } - - @Test - public void givenTwoPanelOnFirstPages_whenRestorePages_thenReturnThosePages() { - givenSavedCurrentPage(0, 1); - givenSavedPageCount(2); - givenPanelCount(2); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(0, 1), result); - } - - @Test - public void givenTwoPanelOnMiddlePages_whenRestorePages_thenReturnThosePages() { - givenSavedCurrentPage(2, 3); - givenSavedPageCount(5); - givenPanelCount(2); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(2, 3), result); - } - - @Test - public void givenTwoPanelOnLastPage_whenRestorePages_thenReturnOnlyLastPage() { - // The device has two panel home but the current page is the last page, so we don't have - // a right panel, only the left one. - givenSavedCurrentPage(2); - givenSavedPageCount(3); - givenPanelCount(2); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(2), result); - } - - @Test - public void givenOnlyOnePageAndPhoneFolding_whenRestorePages_thenReturnOnlyOnePage() { - givenSavedCurrentPage(0); - givenSavedPageCount(1); - givenPanelCount(1); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(0), result); - } - - @Test - public void givenPhoneFolding_whenRestorePages_thenReturnOnlyTheFirstCurrentPage() { - givenSavedCurrentPage(2, 3); - givenSavedPageCount(4); - givenPanelCount(1); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(2), result); - } - - @Test - public void givenPhoneUnfolding_whenRestorePages_thenReturnCurrentPagePlusTheNextOne() { - givenSavedCurrentPage(2); - givenSavedPageCount(4); - givenPanelCount(2); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(2, 3), result); - } - - @Test - public void givenPhoneUnfoldingOnLastPage_whenRestorePages_thenReturnOnlyLastPage() { - givenSavedCurrentPage(4); - givenSavedPageCount(5); - givenPanelCount(2); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(4), result); - } - - @Test - public void givenOnlyOnePageAndPhoneUnfolding_whenRestorePages_thenReturnOnlyOnePage() { - givenSavedCurrentPage(0); - givenSavedPageCount(1); - givenPanelCount(2); - - IntSet result = mPageRestoreHelper.getPagesToRestore(mState); - - assertEquals(IntSet.wrap(0), result); - } - - private void givenPanelCount(int panelCount) { - when(mWorkspace.getPanelCount()).thenReturn(panelCount); - when(mWorkspace.getLeftmostVisiblePageForIndex(anyInt())).thenAnswer(invocation -> { - int pageIndex = invocation.getArgument(0); - return pageIndex * panelCount / panelCount; - }); - } - - private void givenSavedPageCount(int pageCount) { - mState.putInt(RUNTIME_STATE_CURRENT_SCREEN_COUNT, pageCount); - } - - private void givenSavedCurrentPage(int... pages) { - mState.putInt(RUNTIME_STATE_CURRENT_SCREEN, pages[0]); - } -} diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java index ba55834e99..477964a6f4 100644 --- a/src/com/android/launcher3/DeleteDropTarget.java +++ b/src/com/android/launcher3/DeleteDropTarget.java @@ -25,6 +25,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; +import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.logging.StatsLogManager; @@ -128,11 +129,21 @@ public class DeleteDropTarget extends ButtonDropTarget { public void completeDrop(DragObject d) { ItemInfo item = d.dragInfo; if (canRemove(item)) { - int itemPage = mLauncher.getWorkspace().getCurrentPage(); + ItemInfo pageItem = item; + if (item.container <= 0) { + View v = mLauncher.getWorkspace().getHomescreenIconByItemId(item.container); + if (v != null) { + pageItem = (ItemInfo) v.getTag(); + } + } + IntSet pageIds = pageItem.container == Favorites.CONTAINER_DESKTOP + ? IntSet.wrap(pageItem.screenId) + : mLauncher.getWorkspace().getCurrentPageScreenIds(); + onAccessibilityDrop(null, item); ModelWriter modelWriter = mLauncher.getModelWriter(); Runnable onUndoClicked = () -> { - mLauncher.setPagesToBindSynchronously(IntSet.wrap(itemPage)); + mLauncher.setPagesToBindSynchronously(pageIds); modelWriter.abortDelete(); mLauncher.getStatsLogManager().logger().log(LAUNCHER_UNDO); }; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 78a8a9747a..e736022772 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -36,6 +36,7 @@ import static com.android.launcher3.LauncherState.NO_OFFSET; import static com.android.launcher3.LauncherState.NO_SCALE; import static com.android.launcher3.LauncherState.SPRING_LOADED; import static com.android.launcher3.Utilities.postAsyncCallback; +import static com.android.launcher3.WorkspaceLayoutManager.LEFT_PANEL_ID; import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions; import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; @@ -259,6 +260,8 @@ public class Launcher extends StatefulActivity implements Launche private static final String RUNTIME_STATE_PENDING_ACTIVITY_RESULT = "launcher.activity_result"; // Type: SparseArray private static final String RUNTIME_STATE_WIDGET_PANEL = "launcher.widget_panel"; + // Type int[] + private static final String RUNTIME_STATE_CURRENT_SCREEN_IDS = "launcher.current_screen_ids"; public static final String ON_CREATE_EVT = "Launcher.onCreate"; public static final String ON_START_EVT = "Launcher.onStart"; @@ -287,8 +290,6 @@ public class Launcher extends StatefulActivity implements Launche private WidgetManagerHelper mAppWidgetManager; private LauncherAppWidgetHost mAppWidgetHost; - private LauncherPageRestoreHelper mPageRestoreHelper; - private final int[] mTmpAddItemCellCoordinates = new int[2]; @Thunk @@ -325,7 +326,7 @@ public class Launcher extends StatefulActivity implements Launche private PopupDataProvider mPopupDataProvider; private IntSet mSynchronouslyBoundPages = new IntSet(); - private IntSet mPagesToBindSynchronously = new IntSet(); + @NonNull private IntSet mPagesToBindSynchronously = new IntSet(); // We only want to get the SharedPreferences once since it does an FS stat each time we get // it from the context. @@ -460,9 +461,11 @@ public class Launcher extends StatefulActivity implements Launche restoreState(savedInstanceState); mStateManager.reapplyState(); - mPageRestoreHelper = new LauncherPageRestoreHelper(mWorkspace); if (savedInstanceState != null) { - mPagesToBindSynchronously = mPageRestoreHelper.getPagesToRestore(savedInstanceState); + int[] pageIds = savedInstanceState.getIntArray(RUNTIME_STATE_CURRENT_SCREEN_IDS); + if (pageIds != null) { + mPagesToBindSynchronously = IntSet.wrap(pageIds); + } } if (!mModel.addCallbacksAndLoad(this)) { @@ -1188,7 +1191,6 @@ public class Launcher extends StatefulActivity implements Launche // Until the workspace is bound, ensure that we keep the wallpaper offset locked to the // default state, otherwise we will update to the wrong offsets in RTL mWorkspace.lockWallpaperToDefaultPage(); - mWorkspace.bindAndInitLeftPanel(); mWorkspace.bindAndInitFirstWorkspaceScreen(null /* recycled qsb */); mDragController.addDragListener(mWorkspace); @@ -1586,14 +1588,19 @@ public class Launcher extends StatefulActivity implements Launche public void onRestoreInstanceState(Bundle state) { super.onRestoreInstanceState(state); if (mSynchronouslyBoundPages != null) { - mSynchronouslyBoundPages.forEach(page -> mWorkspace.restoreInstanceStateForChild(page)); + mSynchronouslyBoundPages.forEach(screenId -> { + int pageIndex = mWorkspace.getPageIndexForScreenId(screenId); + if (pageIndex != PagedView.INVALID_PAGE) { + mWorkspace.restoreInstanceStateForChild(pageIndex); + } + }); } } @Override protected void onSaveInstanceState(Bundle outState) { - mPageRestoreHelper.savePagesToRestore(outState); - + outState.putIntArray(RUNTIME_STATE_CURRENT_SCREEN_IDS, + mWorkspace.getCurrentPageScreenIds().getArray().toArray()); outState.putInt(RUNTIME_STATE, mStateManager.getState().ordinal); AbstractFloatingView widgets = AbstractFloatingView @@ -2081,18 +2088,42 @@ public class Launcher extends StatefulActivity implements Launche mPagesToBindSynchronously = pages; } - /** - * Implementation of the method from LauncherModel.Callbacks. - */ @Override - public IntSet getPagesToBindSynchronously() { - if (mPagesToBindSynchronously != null && !mPagesToBindSynchronously.isEmpty()) { - return mPagesToBindSynchronously; - } else if (mWorkspace != null) { - return mWorkspace.getVisiblePageIndices(); + public IntSet getPagesToBindSynchronously(IntArray orderedScreenIds) { + IntSet visibleIds = mPagesToBindSynchronously.isEmpty() + ? mWorkspace.getCurrentPageScreenIds() : mPagesToBindSynchronously; + IntArray actualIds = new IntArray(); + + if (mDeviceProfile.isTwoPanels) { + actualIds.add(LEFT_PANEL_ID); } else { - return new IntSet(); + visibleIds.remove(LEFT_PANEL_ID); } + IntSet result = new IntSet(); + if (visibleIds.isEmpty()) { + return result; + } + for (int id : orderedScreenIds.toArray()) { + if (id != LEFT_PANEL_ID) { + actualIds.add(id); + } + } + int firstId = visibleIds.getArray().get(0); + if (actualIds.contains(firstId)) { + result.add(firstId); + + if (mDeviceProfile.isTwoPanels) { + int index = actualIds.indexOf(firstId); + int nextIndex = ((int) (index / 2)) * 2; + if (nextIndex == index) { + nextIndex++; + } + if (nextIndex < actualIds.size()) { + result.add(actualIds.get(nextIndex)); + } + } + } + return result; } /** @@ -2143,7 +2174,7 @@ public class Launcher extends StatefulActivity implements Launche // Make sure the first screen is at the start if there's no widget panel, // or on the second place if the first is the widget panel boolean isLeftPanelShown = - mWorkspace.mWorkspaceScreens.containsKey(Workspace.LEFT_PANEL_ID); + mWorkspace.mWorkspaceScreens.containsKey(LEFT_PANEL_ID); int firstScreenPosition = isLeftPanelShown && orderedScreenIds.size() > 1 ? 1 : 0; if (FeatureFlags.QSB_ON_FIRST_SCREEN && @@ -2171,7 +2202,7 @@ public class Launcher extends StatefulActivity implements Launche continue; } - if (screenId == Workspace.LEFT_PANEL_ID) { + if (screenId == LEFT_PANEL_ID) { // No need to bind the left panel, as its always bound. continue; } @@ -2252,7 +2283,7 @@ public class Launcher extends StatefulActivity implements Launche } // Skip if the item is on the left widget panel but the panel is not shown - if (item.screenId == Workspace.LEFT_PANEL_ID && !getDeviceProfile().isTwoPanels) { + if (item.screenId == LEFT_PANEL_ID && !getDeviceProfile().isTwoPanels) { continue; } @@ -2555,9 +2586,6 @@ public class Launcher extends StatefulActivity implements Launche @Override public void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) { mSynchronouslyBoundPages = boundPages; - if (!boundPages.isEmpty()) { - mWorkspace.setCurrentPage(boundPages.getArray().get(0)); - } mPagesToBindSynchronously = new IntSet(); clearPendingBinds(); @@ -2598,7 +2626,8 @@ public class Launcher extends StatefulActivity implements Launche } int currentPage = pagesBoundFirst != null && !pagesBoundFirst.isEmpty() - ? pagesBoundFirst.getArray().get(0) : PagedView.INVALID_PAGE; + ? mWorkspace.getPageIndexForScreenId(pagesBoundFirst.getArray().get(0)) + : PagedView.INVALID_PAGE; // When undoing the removal of the last item on a page, return to that page. // Since we are just resetting the current page without user interaction, // override the previous page so we don't log the page switch. diff --git a/src/com/android/launcher3/LauncherPageRestoreHelper.java b/src/com/android/launcher3/LauncherPageRestoreHelper.java deleted file mode 100644 index e679a12af7..0000000000 --- a/src/com/android/launcher3/LauncherPageRestoreHelper.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.launcher3; - -import android.os.Bundle; -import android.util.Log; - -import androidx.annotation.VisibleForTesting; - -import com.android.launcher3.util.IntSet; - -import static androidx.annotation.VisibleForTesting.PACKAGE_PRIVATE; - -/** - * There's a logic which prioritizes the binding for the current page and defers the other pages' - * binding. If two panel home is enabled, we want to bind both pages together. - * LauncherPageRestoreHelper's purpose is to contain the logic for persisting, restoring and - * calculating which pages to load immediately. - */ -public class LauncherPageRestoreHelper { - - public static final String TAG = "LauncherPageRestoreHelper"; - - // Type: int - private static final String RUNTIME_STATE_CURRENT_SCREEN = "launcher.current_screen"; - // Type: int - private static final String RUNTIME_STATE_CURRENT_SCREEN_COUNT = - "launcher.current_screen_count"; - - private Workspace mWorkspace; - - public LauncherPageRestoreHelper(Workspace workspace) { - this.mWorkspace = workspace; - } - - /** - * Some configuration changes trigger Launcher to recreate itself, and we want to give more - * priority to the currently active pages in the restoration process. - */ - @VisibleForTesting(otherwise = PACKAGE_PRIVATE) - public IntSet getPagesToRestore(Bundle savedInstanceState) { - IntSet pagesToRestore = new IntSet(); - - if (savedInstanceState == null) { - return pagesToRestore; - } - - int currentPage = savedInstanceState.getInt(RUNTIME_STATE_CURRENT_SCREEN, -1); - int totalPageCount = savedInstanceState.getInt(RUNTIME_STATE_CURRENT_SCREEN_COUNT, -1); - int panelCount = mWorkspace.getPanelCount(); - - if (totalPageCount <= 0 || currentPage < 0) { - Log.e(TAG, "getPagesToRestore: Invalid input: " + totalPageCount + ", " + currentPage); - return pagesToRestore; - } - - int newCurrentPage = mWorkspace.getLeftmostVisiblePageForIndex(currentPage); - for (int page = newCurrentPage; page < newCurrentPage + panelCount - && page < totalPageCount; page++) { - pagesToRestore.add(page); - } - - return pagesToRestore; - } - - /** - * This should be called from Launcher's onSaveInstanceState method to persist everything that - * is necessary to calculate later which pages need to be initialized first after a - * configuration change. - */ - @VisibleForTesting(otherwise = PACKAGE_PRIVATE) - public void savePagesToRestore(Bundle outState) { - int pageCount = mWorkspace.getChildCount(); - if (pageCount > 0) { - outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getCurrentPage()); - outState.putInt(RUNTIME_STATE_CURRENT_SCREEN_COUNT, pageCount); - } - } -} diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 440e9e38dd..a8ed6bcee2 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -61,7 +61,6 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.DbDowngradeHelper; -import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.pm.UserCache; import com.android.launcher3.provider.LauncherDbUtils; import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction; @@ -1090,7 +1089,7 @@ public class LauncherProvider extends ContentProvider { } private int initializeMaxScreenId(SQLiteDatabase db) { - return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s WHERE %3$s = %4$d", + return getMaxId(db, "SELECT MAX(%1$s) FROM %2$s WHERE %3$s = %4$d AND %1$s >= 0", Favorites.SCREEN, Favorites.TABLE_NAME, Favorites.CONTAINER, Favorites.CONTAINER_DESKTOP); } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 6c0e893ad8..faf2dd244f 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -102,6 +102,7 @@ import com.android.launcher3.touch.WorkspaceTouchListener; import com.android.launcher3.util.EdgeEffectCompat; import com.android.launcher3.util.Executors; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSparseArrayMap; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherBindableItemsContainer; @@ -327,22 +328,6 @@ public class Workspace extends PagedView setPageSpacing(Math.max(maxInsets, maxPadding)); } - if (grid.isTwoPanels) { - // Add left widget panel if it isn't already there - if (!mWorkspaceScreens.containsKey(LEFT_PANEL_ID)) { - int newCurrentPage = mCurrentPage + 1; - bindAndInitLeftPanel(); - setCurrentPage(newCurrentPage); - } - } else { - // Remove left widget panel if it is present - if (mWorkspaceScreens.containsKey(LEFT_PANEL_ID)) { - int newCurrentPage = mCurrentPage - 1; - removeLeftPanel(); - setCurrentPage(newCurrentPage); - } - } - int paddingLeftRight = grid.cellLayoutPaddingLeftRightPx; int paddingBottom = grid.cellLayoutBottomPaddingPx; int twoPanelLandscapeSidePadding = paddingLeftRight * 2; @@ -570,6 +555,10 @@ public class Workspace extends PagedView if (!FeatureFlags.QSB_ON_FIRST_SCREEN) { return; } + if (isTwoPanelEnabled()) { + insertNewWorkspaceScreen(Workspace.LEFT_PANEL_ID, getChildCount()); + } + // Add the first page CellLayout firstPage = insertNewWorkspaceScreen(Workspace.FIRST_SCREEN_ID, getChildCount()); // Always add a QSB on the first screen. @@ -590,19 +579,6 @@ public class Workspace extends PagedView } } - /** - * Initializes and binds the left panel - */ - public void bindAndInitLeftPanel() { - if (!FeatureFlags.QSB_ON_FIRST_SCREEN || !isTwoPanelEnabled() - || mWorkspaceScreens.containsKey(Workspace.LEFT_PANEL_ID)) { - return; - } - - insertNewWorkspaceScreen(Workspace.LEFT_PANEL_ID, getChildCount()); - mLauncher.getModelWriter().setLeftPanelShown(true); - } - public void removeAllWorkspaceScreens() { // Disable all layout transitions before removing all pages to ensure that we don't get the // transition animations competing with us changing the scroll when we add pages @@ -624,7 +600,6 @@ public class Workspace extends PagedView mLauncher.mHandler.removeCallbacksAndMessages(DeferredWidgetRefresh.class); // Ensure that the first page is always present - bindAndInitLeftPanel(); bindAndInitFirstWorkspaceScreen(qsb); // Re-enable the layout transitions @@ -645,18 +620,6 @@ public class Workspace extends PagedView insertNewWorkspaceScreen(screenId, getChildCount()); } - private void removeLeftPanel() { - if (!mWorkspaceScreens.containsKey(LEFT_PANEL_ID)) { - return; - } - mLauncher.getModelWriter().setLeftPanelShown(false); - CellLayout leftPanel = mWorkspaceScreens.get(LEFT_PANEL_ID); - mWorkspaceScreens.remove(LEFT_PANEL_ID); - removeView(leftPanel); - mScreenOrder.removeValue(LEFT_PANEL_ID); - updatePageScrollValues(); - } - public CellLayout insertNewWorkspaceScreen(int screenId, int insertIndex) { if (mWorkspaceScreens.containsKey(screenId)) { throw new RuntimeException("Screen id " + screenId + " already exists!"); @@ -829,6 +792,10 @@ public class Workspace extends PagedView return indexOfChild(mWorkspaceScreens.get(screenId)); } + public IntSet getCurrentPageScreenIds() { + return IntSet.wrap(getScreenIdForPageIndex(getCurrentPage())); + } + public int getScreenIdForPageIndex(int index) { if (0 <= index && index < mScreenOrder.size()) { return mScreenOrder.get(index); diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java index 13c83be123..f3087c048f 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -175,7 +175,6 @@ public class PreviewSurfaceRenderer { query); MAIN_EXECUTOR.execute(() -> { - mBgDataModel.isLeftPanelShown = deviceProfile.isTwoPanels; renderView(previewContext, mBgDataModel, mWidgetProvidersMap); mOnDestroyCallbacks.add(previewContext::onDestroy); }); diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index b2b0010fa4..4f12d0b8df 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -15,6 +15,9 @@ */ package com.android.launcher3.model; +import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID; +import static com.android.launcher3.WorkspaceLayoutManager.LEFT_PANEL_ID; + import android.content.Intent; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; @@ -27,6 +30,7 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel.CallbackTask; import com.android.launcher3.LauncherSettings; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.data.AppInfo; @@ -38,6 +42,7 @@ import com.android.launcher3.pm.InstallSessionHelper; import com.android.launcher3.pm.PackageInstallInfo; import com.android.launcher3.util.GridOccupancy; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.IntSet; import com.android.launcher3.util.PackageManagerHelper; import java.util.ArrayList; @@ -291,11 +296,15 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask { boolean found = false; int screenCount = workspaceScreens.size(); - int firstScreenToCheck = dataModel.isLeftPanelShown ? 2 : 1; - // Search on the screens for empty space - for (int screen = firstScreenToCheck; screen < screenCount; screen++) { + // First check the preferred screen. + IntSet screensToExclude = IntSet.wrap(LEFT_PANEL_ID); + if (FeatureFlags.QSB_ON_FIRST_SCREEN) { + screensToExclude.add(FIRST_SCREEN_ID); + } + + for (int screen = 0; screen < screenCount; screen++) { screenId = workspaceScreens.get(screen); - if (findNextAvailableIconSpaceInScreen( + if (!screensToExclude.contains(screenId) && findNextAvailableIconSpaceInScreen( app, screenItems.get(screenId), coordinates, spanX, spanY)) { // We found a space for it found = true; diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java index c202d8d137..0e132c2dad 100644 --- a/src/com/android/launcher3/model/BaseLoaderResults.java +++ b/src/com/android/launcher3/model/BaseLoaderResults.java @@ -165,25 +165,7 @@ public abstract class BaseLoaderResults { } private void bind() { - IntSet currentScreenIndices; - { - // Create an anonymous scope to calculate currentScreen as it has to be a - // final variable. - IntSet screenIndices = mCallbacks.getPagesToBindSynchronously(); - if (screenIndices == null || screenIndices.isEmpty() - || screenIndices.getArray().get(screenIndices.size() - 1) - >= mOrderedScreenIds.size()) { - // There maybe no workspace screens (just hotseat items and an empty page). - // Also we want to prevent IndexOutOfBoundsExceptions. - screenIndices = new IntSet(); - } - currentScreenIndices = screenIndices; - } - - - IntSet currentScreenIds = new IntSet(); - currentScreenIndices.forEach( - index -> currentScreenIds.add(mOrderedScreenIds.get(index))); + IntSet currentScreenIds = mCallbacks.getPagesToBindSynchronously(mOrderedScreenIds); // Separate the items that are on the current screen, and all the other remaining items ArrayList currentWorkspaceItems = new ArrayList<>(); @@ -218,7 +200,7 @@ public abstract class BaseLoaderResults { Executor pendingExecutor = pendingTasks::add; bindWorkspaceItems(otherWorkspaceItems, pendingExecutor); bindAppWidgets(otherAppWidgets, pendingExecutor); - executeCallbacksTask(c -> c.finishBindingItems(currentScreenIndices), pendingExecutor); + executeCallbacksTask(c -> c.finishBindingItems(currentScreenIds), pendingExecutor); pendingExecutor.execute( () -> { MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); @@ -229,7 +211,7 @@ public abstract class BaseLoaderResults { executeCallbacksTask( c -> { MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - c.onInitialBindComplete(currentScreenIndices, pendingTasks); + c.onInitialBindComplete(currentScreenIds, pendingTasks); }, mUiExecutor); } diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java index dd4c3c37a5..13ad90e302 100644 --- a/src/com/android/launcher3/model/BgDataModel.java +++ b/src/com/android/launcher3/model/BgDataModel.java @@ -116,11 +116,6 @@ public class BgDataModel { */ public int lastBindId = 0; - /** - * Value that indicates if left widget panel is shown or not. - */ - public boolean isLeftPanelShown = false; - /** * Clears all the data */ @@ -146,14 +141,6 @@ public class BgDataModel { if (FeatureFlags.QSB_ON_FIRST_SCREEN || screenSet.isEmpty()) { screenSet.add(Workspace.FIRST_SCREEN_ID); } - - if (isLeftPanelShown) { - // We should add it even though there are no items on it. - screenSet.add(Workspace.LEFT_PANEL_ID); - } else { - // We should NOT add it even though there are items on it. - screenSet.remove(Workspace.LEFT_PANEL_ID); - } return screenSet.getArray(); } @@ -459,10 +446,11 @@ public class BgDataModel { int FLAG_QUIET_MODE_CHANGE_PERMISSION = 1 << 2; /** - * Returns an IntSet of page numbers to bind first, synchronously if possible + * Returns an IntSet of page ids to bind first, synchronously if possible * or an empty IntSet + * @param orderedScreenIds All the page ids to be bound */ - default IntSet getPagesToBindSynchronously() { + default IntSet getPagesToBindSynchronously(IntArray orderedScreenIds) { return new IntSet(); } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 31ca6e7c74..43f9be5f80 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -16,6 +16,7 @@ package com.android.launcher3.model; +import static com.android.launcher3.WorkspaceLayoutManager.LEFT_PANEL_ID; import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; @@ -86,6 +87,7 @@ import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IOUtils; +import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.LooperIdleLock; import com.android.launcher3.util.PackageManagerHelper; @@ -175,11 +177,17 @@ public class LoaderTask implements Runnable { private void sendFirstScreenActiveInstallsBroadcast() { ArrayList firstScreenItems = new ArrayList<>(); ArrayList allItems = mBgDataModel.getAllWorkspaceItems(); - // Screen set is never empty - final int firstScreen = mBgDataModel.collectWorkspaceScreens().get(0); - // TODO(b/185515153): support two panel home. - filterCurrentWorkspaceItems(IntSet.wrap(firstScreen), allItems, firstScreenItems, + // Screen set is never empty + IntArray allScreens = mBgDataModel.collectWorkspaceScreens(); + final int firstScreen = allScreens.get(0); + + IntSet firstScreens = IntSet.wrap(firstScreen); + if (firstScreen == LEFT_PANEL_ID && allScreens.size() >= 2) { + firstScreens.add(allScreens.get(1)); + } + + filterCurrentWorkspaceItems(firstScreens, allItems, firstScreenItems, new ArrayList<>() /* otherScreenItems are ignored */); mFirstScreenBroadcast.sendBroadcasts(mApp.getContext(), firstScreenItems); } diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java index 55edfd433a..0439e75843 100644 --- a/src/com/android/launcher3/model/ModelWriter.java +++ b/src/com/android/launcher3/model/ModelWriter.java @@ -121,13 +121,6 @@ public class ModelWriter { } } - /** - * Sets the value that indicates if left widget panel is shown or not. - */ - public void setLeftPanelShown(boolean value) { - mBgDataModel.isLeftPanelShown = value; - } - private void checkItemInfoLocked(int itemId, ItemInfo item, StackTraceElement[] stackTrace) { ItemInfo modelItem = mBgDataModel.itemsIdMap.get(itemId); if (modelItem != null && item != modelItem) {