Snap for 9617930 from 24e2c3cf09 to udc-release
Change-Id: Idc1dd82553917a103d2761f8528c2d048fe69596
This commit is contained in:
@@ -289,6 +289,7 @@
|
||||
|
||||
<!-- Transient taskbar -->
|
||||
<dimen name="transient_taskbar_size">72dp</dimen>
|
||||
<dimen name="transient_taskbar_min_width">150dp</dimen>
|
||||
<dimen name="transient_taskbar_icon_size">48dp</dimen>
|
||||
<dimen name="transient_taskbar_margin">24dp</dimen>
|
||||
<dimen name="transient_taskbar_shadow_blur">40dp</dimen>
|
||||
|
||||
@@ -112,10 +112,23 @@ public class QuickstepModelDelegate extends ModelDelegate {
|
||||
}
|
||||
|
||||
@Override
|
||||
@WorkerThread
|
||||
public void loadItems(UserManagerState ums, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
|
||||
public void loadHotseatItems(UserManagerState ums,
|
||||
Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
|
||||
// TODO: Implement caching and preloading
|
||||
super.loadItems(ums, pinnedShortcuts);
|
||||
super.loadHotseatItems(ums, pinnedShortcuts);
|
||||
|
||||
WorkspaceItemFactory hotseatFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
|
||||
mIDP.numDatabaseHotseatIcons, mHotseatState.containerId);
|
||||
FixedContainerItems hotseatItems = new FixedContainerItems(mHotseatState.containerId,
|
||||
mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
|
||||
mDataModel.extraItems.put(mHotseatState.containerId, hotseatItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAllAppsItems(UserManagerState ums,
|
||||
Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) {
|
||||
// TODO: Implement caching and preloading
|
||||
super.loadAllAppsItems(ums, pinnedShortcuts);
|
||||
|
||||
WorkspaceItemFactory allAppsFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
|
||||
mIDP.numDatabaseAllAppsColumns, mAllAppsState.containerId);
|
||||
@@ -123,17 +136,22 @@ public class QuickstepModelDelegate extends ModelDelegate {
|
||||
mAllAppsState.containerId, mAllAppsState.storage.read(mApp.getContext(),
|
||||
allAppsFactory, ums.allUsers::get));
|
||||
mDataModel.extraItems.put(mAllAppsState.containerId, allAppsPredictionItems);
|
||||
}
|
||||
|
||||
WorkspaceItemFactory hotseatFactory = new WorkspaceItemFactory(mApp, ums, pinnedShortcuts,
|
||||
mIDP.numDatabaseHotseatIcons, mHotseatState.containerId);
|
||||
FixedContainerItems hotseatItems = new FixedContainerItems(mHotseatState.containerId,
|
||||
mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
|
||||
mDataModel.extraItems.put(mHotseatState.containerId, hotseatItems);
|
||||
@Override
|
||||
public void loadWidgetsRecommendationItems() {
|
||||
// TODO: Implement caching and preloading
|
||||
super.loadWidgetsRecommendationItems();
|
||||
|
||||
// Widgets prediction isn't used frequently. And thus, it is not persisted on disk.
|
||||
mDataModel.extraItems.put(mWidgetsRecommendationState.containerId,
|
||||
new FixedContainerItems(mWidgetsRecommendationState.containerId,
|
||||
new ArrayList<>()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markActive() {
|
||||
super.markActive();
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,17 @@ public class FallbackTaskbarUIController extends TaskbarUIController {
|
||||
getRecentsView().setTaskLaunchListener(toState == RecentsState.DEFAULT
|
||||
? (() -> animateToRecentsState(RecentsState.BACKGROUND_APP)) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(RecentsState finalState) {
|
||||
boolean finalStateDefault = finalState == RecentsState.DEFAULT;
|
||||
// TODO(b/268120202) Taskbar shows up on 3P home, currently we don't go to
|
||||
// overview from 3P home. Either implement that or it'll change w/ contextual?
|
||||
boolean disallowLongClick = finalState == RecentsState.OVERVIEW_SPLIT_SELECT;
|
||||
Utilities.setOverviewDragState(mControllers,
|
||||
finalStateDefault /*disallowGlobalDrag*/, disallowLongClick,
|
||||
finalStateDefault /*allowInitialSplitSelection*/);
|
||||
}
|
||||
};
|
||||
|
||||
public FallbackTaskbarUIController(RecentsActivity recentsActivity) {
|
||||
|
||||
@@ -315,6 +315,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
|
||||
@Override
|
||||
public void onTaskbarIconLaunched(ItemInfo item) {
|
||||
super.onTaskbarIconLaunched(item);
|
||||
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
|
||||
mLauncher.logAppLaunch(mControllers.taskbarActivityContext.getStatsLogManager(), item,
|
||||
instanceId);
|
||||
|
||||
@@ -837,15 +837,17 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
launchFromTaskbarPreservingSplitIfVisible(recents, info);
|
||||
}
|
||||
|
||||
mControllers.uiController.onTaskbarIconLaunched(info);
|
||||
} catch (NullPointerException
|
||||
| ActivityNotFoundException
|
||||
| SecurityException e) {
|
||||
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
Log.e(TAG, "Unable to launch. tag=" + info + " intent=" + intent, e);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
mControllers.uiController.onTaskbarIconLaunched(info);
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
|
||||
}
|
||||
} else if (tag instanceof AppInfo) {
|
||||
@@ -859,8 +861,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
taskbarUIController.triggerSecondAppForSplit(info, info.intent, view);
|
||||
} else {
|
||||
launchFromTaskbarPreservingSplitIfVisible(recents, info);
|
||||
mControllers.uiController.onTaskbarIconLaunched(info);
|
||||
}
|
||||
mControllers.uiController.onTaskbarIconLaunched(info);
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
|
||||
} else if (tag instanceof ItemClickProxy) {
|
||||
((ItemClickProxy) tag).onItemClicked(view);
|
||||
|
||||
@@ -119,14 +119,11 @@ import java.util.StringJoiner;
|
||||
mLauncherState = finalState;
|
||||
updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, false);
|
||||
applyState();
|
||||
boolean disallowGlobalDrag = finalState instanceof OverviewState;
|
||||
boolean finalStateOverview = finalState instanceof OverviewState;
|
||||
boolean disallowLongClick = finalState == LauncherState.OVERVIEW_SPLIT_SELECT;
|
||||
mControllers.taskbarDragController.setDisallowGlobalDrag(disallowGlobalDrag);
|
||||
mControllers.taskbarDragController.setDisallowLongClick(disallowLongClick);
|
||||
mControllers.taskbarAllAppsController.setDisallowGlobalDrag(disallowGlobalDrag);
|
||||
mControllers.taskbarAllAppsController.setDisallowLongClick(disallowLongClick);
|
||||
mControllers.taskbarPopupController.setAllowInitialSplitSelection(
|
||||
disallowGlobalDrag);
|
||||
com.android.launcher3.taskbar.Utilities.setOverviewDragState(
|
||||
mControllers, finalStateOverview /*disallowGlobalDrag*/,
|
||||
disallowLongClick, finalStateOverview /*allowInitialSplitSelection*/);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -199,13 +199,6 @@ public class TaskbarModelCallbacks implements
|
||||
hotseatItemInfos = mControllers.taskbarRecentAppsController
|
||||
.updateHotseatItemInfos(hotseatItemInfos);
|
||||
mContainer.updateHotseatItems(hotseatItemInfos);
|
||||
|
||||
final boolean finalIsHotseatEmpty = isHotseatEmpty;
|
||||
mControllers.runAfterInit(() -> {
|
||||
mControllers.taskbarStashController.updateStateForFlag(
|
||||
TaskbarStashController.FLAG_STASHED_IN_APP_EMPTY, finalIsHotseatEmpty);
|
||||
mControllers.taskbarStashController.applyState();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -72,21 +72,20 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
public static final int FLAG_IN_APP = 1 << 0;
|
||||
public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
|
||||
public static final int FLAG_STASHED_IN_SYSUI_STATE = 1 << 2; // app pinning, keyguard, etc.
|
||||
public static final int FLAG_STASHED_IN_APP_EMPTY = 1 << 3; // no hotseat icons
|
||||
public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
|
||||
public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible
|
||||
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
|
||||
public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 7; // All apps is visible.
|
||||
public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard
|
||||
public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 9; // phone screen gesture nav, stashed
|
||||
public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 10; // Autohide (transient taskbar).
|
||||
public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 3; // setup wizard and AllSetActivity
|
||||
public static final int FLAG_STASHED_IN_APP_IME = 1 << 4; // IME is visible
|
||||
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 5;
|
||||
public static final int FLAG_STASHED_IN_TASKBAR_ALL_APPS = 1 << 6; // All apps is visible.
|
||||
public static final int FLAG_IN_SETUP = 1 << 7; // In the Setup Wizard
|
||||
public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 8; // phone screen gesture nav, stashed
|
||||
public static final int FLAG_STASHED_IN_APP_AUTO = 1 << 9; // Autohide (transient taskbar).
|
||||
|
||||
// If any of these flags are enabled, isInApp should return true.
|
||||
private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
|
||||
|
||||
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
|
||||
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
|
||||
| FLAG_STASHED_IN_SYSUI_STATE | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
|
||||
| FLAG_STASHED_IN_SYSUI_STATE | FLAG_STASHED_IN_APP_SETUP
|
||||
| FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_TASKBAR_ALL_APPS
|
||||
| FLAG_STASHED_SMALL_SCREEN | FLAG_STASHED_IN_APP_AUTO;
|
||||
|
||||
@@ -932,7 +931,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
appendFlag(sj, flags, FLAGS_IN_APP, "FLAG_IN_APP");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_MANUAL, "FLAG_STASHED_IN_APP_MANUAL");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_SYSUI_STATE, "FLAG_STASHED_IN_SYSUI_STATE");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_EMPTY, "FLAG_STASHED_IN_APP_EMPTY");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_SETUP, "FLAG_STASHED_IN_APP_SETUP");
|
||||
appendFlag(sj, flags, FLAG_STASHED_IN_APP_IME, "FLAG_STASHED_IN_APP_IME");
|
||||
appendFlag(sj, flags, FLAG_IN_STASHED_LAUNCHER_STATE, "FLAG_IN_STASHED_LAUNCHER_STATE");
|
||||
|
||||
@@ -17,6 +17,8 @@ package com.android.launcher3.taskbar;
|
||||
|
||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_IN_APP;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.view.MotionEvent;
|
||||
@@ -74,7 +76,13 @@ public class TaskbarUIController {
|
||||
protected void onStashedInAppChanged() { }
|
||||
|
||||
/** Called when an icon is launched. */
|
||||
public void onTaskbarIconLaunched(ItemInfo item) { }
|
||||
@CallSuper
|
||||
public void onTaskbarIconLaunched(ItemInfo item) {
|
||||
// When launching from Taskbar, e.g. from Overview, set FLAG_IN_APP immediately instead of
|
||||
// waiting for onPause, to reduce potential visual noise during the app open transition.
|
||||
mControllers.taskbarStashController.updateStateForFlag(FLAG_IN_APP, true);
|
||||
mControllers.taskbarStashController.applyState();
|
||||
}
|
||||
|
||||
public View getRootView() {
|
||||
return mControllers.taskbarActivityContext.getDragLayer();
|
||||
@@ -104,7 +112,7 @@ public class TaskbarUIController {
|
||||
public void onExpandPip() {
|
||||
if (mControllers != null) {
|
||||
final TaskbarStashController stashController = mControllers.taskbarStashController;
|
||||
stashController.updateStateForFlag(TaskbarStashController.FLAG_IN_APP, true);
|
||||
stashController.updateStateForFlag(FLAG_IN_APP, true);
|
||||
stashController.applyState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
|
||||
private View mQsb;
|
||||
|
||||
private float mTransientTaskbarMinWidth;
|
||||
|
||||
public TaskbarView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@@ -108,6 +110,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
mIconLayoutBounds = mActivityContext.getTransientTaskbarBounds();
|
||||
Resources resources = getResources();
|
||||
mIsRtl = Utilities.isRtl(resources);
|
||||
mTransientTaskbarMinWidth = mContext.getResources().getDimension(
|
||||
R.dimen.transient_taskbar_min_width);
|
||||
|
||||
int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
|
||||
int actualIconSize = mActivityContext.getDeviceProfile().iconSizePx;
|
||||
@@ -124,11 +128,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
|
||||
mThemeIconsBackground = calculateThemeIconsBackground();
|
||||
|
||||
if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()
|
||||
&& !mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
|
||||
if (!mActivityContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
|
||||
mAllAppsButton = (IconButtonView) LayoutInflater.from(context)
|
||||
.inflate(R.layout.taskbar_all_apps_button, this, false);
|
||||
mAllAppsButton.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
|
||||
mAllAppsButton.setScaleX(mIsRtl ? -1 : 1);
|
||||
mAllAppsButton.setForegroundTint(mActivityContext.getColor(
|
||||
DisplayController.isTransientTaskbar(mActivityContext)
|
||||
@@ -277,7 +279,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
if (mAllAppsButton != null) {
|
||||
addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
|
||||
|
||||
if (mTaskbarDivider != null) {
|
||||
// if only all apps button present, don't include divider view.
|
||||
if (mTaskbarDivider != null && getChildCount() > 1) {
|
||||
addView(mTaskbarDivider, mIsRtl ? (getChildCount() - 1) : 1);
|
||||
}
|
||||
}
|
||||
@@ -319,6 +322,11 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
int count = getChildCount();
|
||||
DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
|
||||
int spaceNeeded = getIconLayoutWidth();
|
||||
// We are removing the margin from taskbar divider item in taskbar,
|
||||
// so remove it from spacing also.
|
||||
if (FeatureFlags.ENABLE_TASKBAR_PINNING.get() && count > 1) {
|
||||
spaceNeeded -= mIconTouchSize;
|
||||
}
|
||||
int navSpaceNeeded = deviceProfile.hotseatBarEndOffset;
|
||||
boolean layoutRtl = isLayoutRtl();
|
||||
int iconEnd = right - (right - left - spaceNeeded) / 2;
|
||||
@@ -362,7 +370,15 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
iconEnd = iconStart - mItemMarginLeftRight;
|
||||
}
|
||||
}
|
||||
|
||||
mIconLayoutBounds.left = iconEnd;
|
||||
|
||||
if (mIconLayoutBounds.right - mIconLayoutBounds.left < mTransientTaskbarMinWidth) {
|
||||
int center = mIconLayoutBounds.centerX();
|
||||
int distanceFromCenter = (int) mTransientTaskbarMinWidth / 2;
|
||||
mIconLayoutBounds.right = center + distanceFromCenter;
|
||||
mIconLayoutBounds.left = center - distanceFromCenter;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -519,6 +535,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
|
||||
/**
|
||||
* Finds the first icon to match one of the given matchers, from highest to lowest priority.
|
||||
*
|
||||
* @return The first match, or All Apps button if no match was found.
|
||||
*/
|
||||
public View getFirstMatch(Predicate<ItemInfo>... matchers) {
|
||||
|
||||
@@ -380,8 +380,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
|
||||
View child = mTaskbarView.getChildAt(i);
|
||||
int positionInHotseat;
|
||||
boolean isAllAppsButton = FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()
|
||||
&& child == mTaskbarView.getAllAppsButtonView();
|
||||
boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonView();
|
||||
if (!mIsHotseatIconOnTopWhenAligned) {
|
||||
// When going to home, the EMPHASIZED interpolator in TaskbarLauncherStateController
|
||||
// plays iconAlignment to 1 really fast, therefore moving the fading towards the end
|
||||
@@ -630,7 +629,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
}
|
||||
|
||||
public static final FloatProperty<View> ICON_TRANSLATE_X =
|
||||
new FloatProperty<View>("taskbarAligmentTranslateX") {
|
||||
new FloatProperty<View>("taskbarAlignmentTranslateX") {
|
||||
|
||||
@Override
|
||||
public void setValue(View view, float v) {
|
||||
|
||||
@@ -30,4 +30,18 @@ public final class Utilities {
|
||||
str.add(flagName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets drag, long-click, and split selection behavior on 1P and 3P launchers with Taskbar
|
||||
*/
|
||||
static void setOverviewDragState(TaskbarControllers controllers,
|
||||
boolean disallowGlobalDrag, boolean disallowLongClick,
|
||||
boolean allowInitialSplitSelection) {
|
||||
controllers.taskbarDragController.setDisallowGlobalDrag(disallowGlobalDrag);
|
||||
controllers.taskbarDragController.setDisallowLongClick(disallowLongClick);
|
||||
controllers.taskbarAllAppsController.setDisallowGlobalDrag(disallowGlobalDrag);
|
||||
controllers.taskbarAllAppsController.setDisallowLongClick(disallowLongClick);
|
||||
controllers.taskbarPopupController.setAllowInitialSplitSelection(
|
||||
allowInitialSplitSelection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.appprediction.PredictionRowView;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.taskbar.TaskbarControllers;
|
||||
@@ -54,9 +53,6 @@ public final class TaskbarAllAppsController {
|
||||
|
||||
/** Initialize the controller. */
|
||||
public void init(TaskbarControllers controllers, boolean allAppsVisible) {
|
||||
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
|
||||
return;
|
||||
}
|
||||
mControllers = controllers;
|
||||
|
||||
/*
|
||||
@@ -70,10 +66,6 @@ public final class TaskbarAllAppsController {
|
||||
|
||||
/** Updates the current {@link AppInfo} instances. */
|
||||
public void setApps(AppInfo[] apps, int flags) {
|
||||
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mApps = apps;
|
||||
mAppsModelFlags = flags;
|
||||
if (mAppsView != null) {
|
||||
@@ -91,10 +83,6 @@ public final class TaskbarAllAppsController {
|
||||
|
||||
/** Updates the current predictions. */
|
||||
public void setPredictedApps(List<ItemInfo> predictedApps) {
|
||||
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPredictedApps = predictedApps;
|
||||
if (mAppsView != null) {
|
||||
mAppsView.getFloatingHeaderView()
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.android.launcher3.taskbar
|
||||
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.launcher3.statemanager.StateManager
|
||||
import com.android.quickstep.RecentsActivity
|
||||
import com.android.quickstep.fallback.RecentsState
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations.initMocks
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FallbackTaskbarUIControllerTest : TaskbarBaseTestCase() {
|
||||
|
||||
lateinit var fallbackTaskbarUIController: FallbackTaskbarUIController
|
||||
lateinit var stateListener: StateManager.StateListener<RecentsState>
|
||||
|
||||
@Mock
|
||||
lateinit var recentsActivity: RecentsActivity
|
||||
@Mock
|
||||
lateinit var stateManager: StateManager<RecentsState>
|
||||
|
||||
@Before
|
||||
override fun setup() {
|
||||
super.setup()
|
||||
whenever(recentsActivity.stateManager).thenReturn(stateManager)
|
||||
fallbackTaskbarUIController = FallbackTaskbarUIController(recentsActivity)
|
||||
|
||||
// Capture registered state listener to send events to in our tests
|
||||
val captor = ArgumentCaptor.forClass(StateManager.StateListener::class.java)
|
||||
fallbackTaskbarUIController.init(taskbarControllers)
|
||||
verify(stateManager).addStateListener(captor.capture())
|
||||
stateListener = captor.value as StateManager.StateListener<RecentsState>
|
||||
}
|
||||
|
||||
@Test
|
||||
fun stateTransitionComplete_stateDefault() {
|
||||
stateListener.onStateTransitionComplete(RecentsState.DEFAULT)
|
||||
// verify dragging disabled
|
||||
verify(taskbarDragController, times(1)).setDisallowGlobalDrag(true)
|
||||
verify(taskbarAllAppsController, times(1)).setDisallowGlobalDrag(true)
|
||||
// verify long click enabled
|
||||
verify(taskbarDragController, times(1)).setDisallowLongClick(false)
|
||||
verify(taskbarAllAppsController, times(1)).setDisallowLongClick(false)
|
||||
// verify split selection enabled
|
||||
verify(taskbarPopupController, times(1)).setAllowInitialSplitSelection(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun stateTransitionComplete_stateSplitSelect() {
|
||||
stateListener.onStateTransitionComplete(RecentsState.OVERVIEW_SPLIT_SELECT)
|
||||
// verify dragging disabled
|
||||
verify(taskbarDragController, times(1)).setDisallowGlobalDrag(false)
|
||||
verify(taskbarAllAppsController, times(1)).setDisallowGlobalDrag(false)
|
||||
// verify long click enabled
|
||||
verify(taskbarDragController, times(1)).setDisallowLongClick(true)
|
||||
verify(taskbarAllAppsController, times(1)).setDisallowLongClick(true)
|
||||
// verify split selection enabled
|
||||
verify(taskbarPopupController, times(1)).setAllowInitialSplitSelection(false)
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ abstract class TaskbarBaseTestCase {
|
||||
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
|
||||
@Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
|
||||
|
||||
lateinit var mTaskbarControllers: TaskbarControllers
|
||||
lateinit var taskbarControllers: TaskbarControllers
|
||||
|
||||
@Before
|
||||
open fun setup() {
|
||||
@@ -66,7 +66,7 @@ abstract class TaskbarBaseTestCase {
|
||||
* includes that method to allow mocking it.
|
||||
*/
|
||||
MockitoAnnotations.initMocks(this)
|
||||
mTaskbarControllers =
|
||||
taskbarControllers =
|
||||
TaskbarControllers(
|
||||
taskbarActivityContext,
|
||||
taskbarDragController,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2022 The Android Open Source Project
|
||||
<!-- Copyright (C) 2023 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -13,43 +13,36 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="29dp"
|
||||
android:height="28dp"
|
||||
android:viewportWidth="29"
|
||||
android:viewportHeight="28">
|
||||
<group
|
||||
android:pivotY="14.5"
|
||||
android:pivotX="22"
|
||||
android:scaleX=".50"
|
||||
android:scaleY=".50">
|
||||
<path
|
||||
android:pathData="M4 7C3.0375 7 2.215 6.65 1.5325 5.9675C0.85 5.285 0.5 4.4625 0.5 3.5C0.5 2.5375 0.85 1.715 1.5325 1.0325C2.215 0.35 3.0375 0 4 0C4.9625 0 5.785 0.35 6.4675 1.0325C7.15 1.715 7.5 2.5375 7.5 3.5C7.5 4.4625 7.15 5.285 6.4675 5.9675C5.785 6.65 4.9625 7 4 7Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M14.5 7C13.5375 7 12.715 6.65 12.0325 5.9675C11.35 5.285 11 4.4625 11 3.5C11 2.5375 11.35 1.715 12.0325 1.0325C12.715 0.35 13.5375 0 14.5 0C15.4625 0 16.285 0.35 16.9675 1.0325C17.65 1.715 18 2.5375 18 3.5C18 4.4625 17.65 5.285 16.9675 5.9675C16.285 6.65 15.4625 7 14.5 7Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M25 7C24.0375 7 23.215 6.65 22.5325 5.9675C21.85 5.285 21.5 4.4625 21.5 3.5C21.5 2.5375 21.85 1.715 22.5325 1.0325C23.215 0.35 24.0375 0 25 0C25.9625 0 26.785 0.35 27.4675 1.0325C28.15 1.715 28.5 2.5375 28.5 3.5C28.5 4.4625 28.15 5.285 27.4675 5.9675C26.785 6.65 25.9625 7 25 7Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M4 17.5C3.0375 17.5 2.215 17.15 1.5325 16.4675C0.85 15.785 0.5 14.9625 0.5 14C0.5 13.0375 0.85 12.215 1.5325 11.5325C2.215 10.85 3.0375 10.5 4 10.5C4.9625 10.5 5.785 10.85 6.4675 11.5325C7.15 12.215 7.5 13.0375 7.5 14C7.5 14.9625 7.15 15.785 6.4675 16.4675C5.785 17.15 4.9625 17.5 4 17.5Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M14.5 17.5C13.5375 17.5 12.715 17.15 12.0325 16.4675C11.35 15.785 11 14.9625 11 14C11 13.0375 11.35 12.215 12.0325 11.5325C12.715 10.85 13.5375 10.5 14.5 10.5C15.4625 10.5 16.285 10.85 16.9675 11.5325C17.65 12.215 18 13.0375 18 14C18 14.9625 17.65 15.785 16.9675 16.4675C16.285 17.15 15.4625 17.5 14.5 17.5Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M25 17.5C24.0375 17.5 23.215 17.15 22.5325 16.4675C21.85 15.785 21.5 14.9625 21.5 14C21.5 13.0375 21.85 12.215 22.5325 11.5325C23.215 10.85 24.0375 10.5 25 10.5C25.9625 10.5 26.785 10.85 27.4675 11.5325C28.15 12.215 28.5 13.0375 28.5 14C28.5 14.9625 28.15 15.785 27.4675 16.4675C26.785 17.15 25.9625 17.5 25 17.5Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M4 28C3.0375 28 2.215 27.65 1.5325 26.9675C0.85 26.285 0.5 25.4625 0.5 24.5C0.5 23.5375 0.85 22.715 1.5325 22.0325C2.215 21.35 3.0375 21 4 21C4.9625 21 5.785 21.35 6.4675 22.0325C7.15 22.715 7.5 23.5375 7.5 24.5C7.5 25.4625 7.15 26.285 6.4675 26.9675C5.785 27.65 4.9625 28 4 28Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M14.5 28C13.5375 28 12.715 27.65 12.0325 26.9675C11.35 26.285 11 25.4625 11 24.5C11 23.5375 11.35 22.715 12.0325 22.0325C12.715 21.35 13.5375 21 14.5 21C15.4625 21 16.285 21.35 16.9675 22.0325C17.65 22.715 18 23.5375 18 24.5C18 25.4625 17.65 26.285 16.9675 26.9675C16.285 27.65 15.4625 28 14.5 28Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
<path
|
||||
android:pathData="M25 28C24.0375 28 23.215 27.65 22.5325 26.9675C21.85 26.285 21.5 25.4625 21.5 24.5C21.5 23.5375 21.85 22.715 22.5325 22.0325C23.215 21.35 24.0375 21 25 21C25.9625 21 26.785 21.35 27.4675 22.0325C28.15 22.715 28.5 23.5375 28.5 24.5C28.5 25.4625 28.15 26.285 27.4675 26.9675C26.785 27.65 25.9625 28 25 28Z"
|
||||
android:fillColor="@color/all_apps_button_color"/>
|
||||
</group>
|
||||
android:width="52dp"
|
||||
android:height="52dp"
|
||||
android:viewportWidth="52"
|
||||
android:viewportHeight="52">
|
||||
<path
|
||||
android:pathData="M15.5,19C14.538,19 13.715,18.65 13.033,17.968C12.35,17.285 12,16.462 12,15.5C12,14.538 12.35,13.715 13.033,13.033C13.715,12.35 14.538,12 15.5,12C16.462,12 17.285,12.35 17.968,13.033C18.65,13.715 19,14.538 19,15.5C19,16.462 18.65,17.285 17.968,17.968C17.285,18.65 16.462,19 15.5,19Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M26,19C25.038,19 24.215,18.65 23.532,17.968C22.85,17.285 22.5,16.462 22.5,15.5C22.5,14.538 22.85,13.715 23.532,13.033C24.215,12.35 25.038,12 26,12C26.962,12 27.785,12.35 28.468,13.033C29.15,13.715 29.5,14.538 29.5,15.5C29.5,16.462 29.15,17.285 28.468,17.968C27.785,18.65 26.962,19 26,19Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M36.5,19C35.537,19 34.715,18.65 34.033,17.968C33.35,17.285 33,16.462 33,15.5C33,14.538 33.35,13.715 34.033,13.033C34.715,12.35 35.537,12 36.5,12C37.463,12 38.285,12.35 38.967,13.033C39.65,13.715 40,14.538 40,15.5C40,16.462 39.65,17.285 38.967,17.968C38.285,18.65 37.463,19 36.5,19Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M15.5,29.5C14.538,29.5 13.715,29.15 13.033,28.468C12.35,27.785 12,26.962 12,26C12,25.038 12.35,24.215 13.033,23.532C13.715,22.85 14.538,22.5 15.5,22.5C16.462,22.5 17.285,22.85 17.968,23.532C18.65,24.215 19,25.038 19,26C19,26.962 18.65,27.785 17.968,28.468C17.285,29.15 16.462,29.5 15.5,29.5Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M26,29.5C25.038,29.5 24.215,29.15 23.532,28.468C22.85,27.785 22.5,26.962 22.5,26C22.5,25.038 22.85,24.215 23.532,23.532C24.215,22.85 25.038,22.5 26,22.5C26.962,22.5 27.785,22.85 28.468,23.532C29.15,24.215 29.5,25.038 29.5,26C29.5,26.962 29.15,27.785 28.468,28.468C27.785,29.15 26.962,29.5 26,29.5Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M36.5,29.5C35.537,29.5 34.715,29.15 34.033,28.468C33.35,27.785 33,26.962 33,26C33,25.038 33.35,24.215 34.033,23.532C34.715,22.85 35.537,22.5 36.5,22.5C37.463,22.5 38.285,22.85 38.967,23.532C39.65,24.215 40,25.038 40,26C40,26.962 39.65,27.785 38.967,28.468C38.285,29.15 37.463,29.5 36.5,29.5Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M15.5,40C14.538,40 13.715,39.65 13.033,38.967C12.35,38.285 12,37.463 12,36.5C12,35.537 12.35,34.715 13.033,34.033C13.715,33.35 14.538,33 15.5,33C16.462,33 17.285,33.35 17.968,34.033C18.65,34.715 19,35.537 19,36.5C19,37.463 18.65,38.285 17.968,38.967C17.285,39.65 16.462,40 15.5,40Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M26,40C25.038,40 24.215,39.65 23.532,38.967C22.85,38.285 22.5,37.463 22.5,36.5C22.5,35.537 22.85,34.715 23.532,34.033C24.215,33.35 25.038,33 26,33C26.962,33 27.785,33.35 28.468,34.033C29.15,34.715 29.5,35.537 29.5,36.5C29.5,37.463 29.15,38.285 28.468,38.967C27.785,39.65 26.962,40 26,40Z"
|
||||
android:fillColor="#40484B"/>
|
||||
<path
|
||||
android:pathData="M36.5,40C35.537,40 34.715,39.65 34.033,38.967C33.35,38.285 33,37.463 33,36.5C33,35.537 33.35,34.715 34.033,34.033C34.715,33.35 35.537,33 36.5,33C37.463,33 38.285,33.35 38.967,34.033C39.65,34.715 40,35.537 40,36.5C40,37.463 39.65,38.285 38.967,38.967C38.285,39.65 37.463,40 36.5,40Z"
|
||||
android:fillColor="#40484B"/>
|
||||
</vector>
|
||||
|
||||
@@ -230,10 +230,6 @@ public final class FeatureFlags {
|
||||
"ENABLE_ICON_LABEL_AUTO_SCALING", true,
|
||||
"Enables scaling/spacing for icon labels to make more characters visible");
|
||||
|
||||
public static final BooleanFlag ENABLE_ALL_APPS_IN_TASKBAR = getDebugFlag(
|
||||
"ENABLE_ALL_APPS_IN_TASKBAR", true,
|
||||
"Enables accessing All Apps from the system Taskbar.");
|
||||
|
||||
public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(
|
||||
"ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT", false,
|
||||
"Enables displaying the all apps button in the hotseat.");
|
||||
|
||||
@@ -37,7 +37,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.Workspace;
|
||||
@@ -72,24 +71,32 @@ public class LoaderCursor extends CursorWrapper {
|
||||
private final IconCache mIconCache;
|
||||
private final InvariantDeviceProfile mIDP;
|
||||
|
||||
private final IntArray itemsToRemove = new IntArray();
|
||||
private final IntArray restoredRows = new IntArray();
|
||||
private final IntSparseArrayMap<GridOccupancy> occupied = new IntSparseArrayMap<>();
|
||||
private final IntArray mItemsToRemove = new IntArray();
|
||||
private final IntArray mRestoredRows = new IntArray();
|
||||
private final IntSparseArrayMap<GridOccupancy> mOccupied = new IntSparseArrayMap<>();
|
||||
|
||||
private final int iconPackageIndex;
|
||||
private final int iconResourceIndex;
|
||||
private final int iconIndex;
|
||||
public final int titleIndex;
|
||||
private final int mIconPackageIndex;
|
||||
private final int mIconResourceIndex;
|
||||
private final int mIconIndex;
|
||||
public final int mTitleIndex;
|
||||
|
||||
private final int idIndex;
|
||||
private final int containerIndex;
|
||||
private final int itemTypeIndex;
|
||||
private final int screenIndex;
|
||||
private final int cellXIndex;
|
||||
private final int cellYIndex;
|
||||
private final int profileIdIndex;
|
||||
private final int restoredIndex;
|
||||
private final int intentIndex;
|
||||
private final int mIdIndex;
|
||||
private final int mContainerIndex;
|
||||
private final int mItemTypeIndex;
|
||||
private final int mScreenIndex;
|
||||
private final int mCellXIndex;
|
||||
private final int mCellYIndex;
|
||||
private final int mProfileIdIndex;
|
||||
private final int mRestoredIndex;
|
||||
private final int mIntentIndex;
|
||||
|
||||
private final int mAppWidgetIdIndex;
|
||||
private final int mAppWidgetProviderIndex;
|
||||
private final int mSpanXIndex;
|
||||
private final int mSpanYIndex;
|
||||
private final int mRankIndex;
|
||||
private final int mOptionsIndex;
|
||||
private final int mAppWidgetSourceIndex;
|
||||
|
||||
@Nullable
|
||||
private LauncherActivityInfo mActivityInfo;
|
||||
@@ -114,20 +121,28 @@ public class LoaderCursor extends CursorWrapper {
|
||||
mPM = mContext.getPackageManager();
|
||||
|
||||
// Init column indices
|
||||
iconIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
|
||||
iconPackageIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
|
||||
iconResourceIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
|
||||
titleIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
|
||||
mIconIndex = getColumnIndexOrThrow(Favorites.ICON);
|
||||
mIconPackageIndex = getColumnIndexOrThrow(Favorites.ICON_PACKAGE);
|
||||
mIconResourceIndex = getColumnIndexOrThrow(Favorites.ICON_RESOURCE);
|
||||
mTitleIndex = getColumnIndexOrThrow(Favorites.TITLE);
|
||||
|
||||
idIndex = getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
|
||||
containerIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
|
||||
itemTypeIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
|
||||
screenIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
|
||||
cellXIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
|
||||
cellYIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
|
||||
profileIdIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);
|
||||
restoredIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.RESTORED);
|
||||
intentIndex = getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
|
||||
mIdIndex = getColumnIndexOrThrow(Favorites._ID);
|
||||
mContainerIndex = getColumnIndexOrThrow(Favorites.CONTAINER);
|
||||
mItemTypeIndex = getColumnIndexOrThrow(Favorites.ITEM_TYPE);
|
||||
mScreenIndex = getColumnIndexOrThrow(Favorites.SCREEN);
|
||||
mCellXIndex = getColumnIndexOrThrow(Favorites.CELLX);
|
||||
mCellYIndex = getColumnIndexOrThrow(Favorites.CELLY);
|
||||
mProfileIdIndex = getColumnIndexOrThrow(Favorites.PROFILE_ID);
|
||||
mRestoredIndex = getColumnIndexOrThrow(Favorites.RESTORED);
|
||||
mIntentIndex = getColumnIndexOrThrow(Favorites.INTENT);
|
||||
|
||||
mAppWidgetIdIndex = getColumnIndexOrThrow(Favorites.APPWIDGET_ID);
|
||||
mAppWidgetProviderIndex = getColumnIndexOrThrow(Favorites.APPWIDGET_PROVIDER);
|
||||
mSpanXIndex = getColumnIndexOrThrow(Favorites.SPANX);
|
||||
mSpanYIndex = getColumnIndexOrThrow(Favorites.SPANY);
|
||||
mRankIndex = getColumnIndexOrThrow(Favorites.RANK);
|
||||
mOptionsIndex = getColumnIndexOrThrow(Favorites.OPTIONS);
|
||||
mAppWidgetSourceIndex = getColumnIndexOrThrow(Favorites.APPWIDGET_SOURCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,18 +152,18 @@ public class LoaderCursor extends CursorWrapper {
|
||||
mActivityInfo = null;
|
||||
|
||||
// Load common properties.
|
||||
itemType = getInt(itemTypeIndex);
|
||||
container = getInt(containerIndex);
|
||||
id = getInt(idIndex);
|
||||
serialNumber = getInt(profileIdIndex);
|
||||
itemType = getInt(mItemTypeIndex);
|
||||
container = getInt(mContainerIndex);
|
||||
id = getInt(mIdIndex);
|
||||
serialNumber = getInt(mProfileIdIndex);
|
||||
user = allUsers.get(serialNumber);
|
||||
restoreFlag = getInt(restoredIndex);
|
||||
restoreFlag = getInt(mRestoredIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Intent parseIntent() {
|
||||
String intentDescription = getString(intentIndex);
|
||||
String intentDescription = getString(mIntentIndex);
|
||||
try {
|
||||
return TextUtils.isEmpty(intentDescription) ?
|
||||
null : Intent.parseUri(intentDescription, 0);
|
||||
@@ -185,14 +200,14 @@ public class LoaderCursor extends CursorWrapper {
|
||||
|
||||
public IconRequestInfo<WorkspaceItemInfo> createIconRequestInfo(
|
||||
WorkspaceItemInfo wai, boolean useLowResIcon) {
|
||||
String packageName = itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
|
||||
? getString(iconPackageIndex) : null;
|
||||
String resourceName = itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
|
||||
? getString(iconResourceIndex) : null;
|
||||
byte[] iconBlob = itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
|
||||
String packageName = itemType == Favorites.ITEM_TYPE_SHORTCUT
|
||||
? getString(mIconPackageIndex) : null;
|
||||
String resourceName = itemType == Favorites.ITEM_TYPE_SHORTCUT
|
||||
? getString(mIconResourceIndex) : null;
|
||||
byte[] iconBlob = itemType == Favorites.ITEM_TYPE_SHORTCUT
|
||||
|| itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
|
||||
|| restoreFlag != 0
|
||||
? getBlob(iconIndex) : null;
|
||||
? getBlob(mIconIndex) : null;
|
||||
|
||||
return new IconRequestInfo<>(
|
||||
wai, mActivityInfo, packageName, resourceName, iconBlob, useLowResIcon);
|
||||
@@ -202,7 +217,70 @@ public class LoaderCursor extends CursorWrapper {
|
||||
* Returns the title or empty string
|
||||
*/
|
||||
private String getTitle() {
|
||||
return Utilities.trim(getString(titleIndex));
|
||||
return Utilities.trim(getString(mTitleIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
* When loading an app widget for the workspace, returns it's app widget id
|
||||
*/
|
||||
public int getAppWidgetId() {
|
||||
return getInt(mAppWidgetIdIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* When loading an app widget for the workspace, returns the widget provider
|
||||
*/
|
||||
public String getAppWidgetProvider() {
|
||||
return getString(mAppWidgetProviderIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x position for the item in the cell layout's grid
|
||||
*/
|
||||
public int getSpanX() {
|
||||
return getInt(mSpanXIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y position for the item in the cell layout's grid
|
||||
*/
|
||||
public int getSpanY() {
|
||||
return getInt(mSpanYIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the rank for the item
|
||||
*/
|
||||
public int getRank() {
|
||||
return getInt(mRankIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the options for the item
|
||||
*/
|
||||
public int getOptions() {
|
||||
return getInt(mOptionsIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* When loading an app widget for the workspace, returns it's app widget source
|
||||
*/
|
||||
public int getAppWidgetSource() {
|
||||
return getInt(mAppWidgetSourceIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the screen that the item is on
|
||||
*/
|
||||
public int getScreen() {
|
||||
return getInt(mScreenIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the UX container that the item is in
|
||||
*/
|
||||
public int getContainer() {
|
||||
return getInt(mContainerIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,7 +398,7 @@ public class LoaderCursor extends CursorWrapper {
|
||||
*/
|
||||
public void markDeleted(String reason) {
|
||||
FileLog.e(TAG, reason);
|
||||
itemsToRemove.add(id);
|
||||
mItemsToRemove.add(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,10 +406,10 @@ public class LoaderCursor extends CursorWrapper {
|
||||
* @return true is any item was removed.
|
||||
*/
|
||||
public boolean commitDeleted() {
|
||||
if (itemsToRemove.size() > 0) {
|
||||
if (mItemsToRemove.size() > 0) {
|
||||
// Remove dead items
|
||||
mContext.getContentResolver().delete(mContentUri, Utilities.createDbSelectionQuery(
|
||||
LauncherSettings.Favorites._ID, itemsToRemove), null);
|
||||
Favorites._ID, mItemsToRemove), null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -342,7 +420,7 @@ public class LoaderCursor extends CursorWrapper {
|
||||
*/
|
||||
public void markRestored() {
|
||||
if (restoreFlag != 0) {
|
||||
restoredRows.add(id);
|
||||
mRestoredRows.add(id);
|
||||
restoreFlag = 0;
|
||||
}
|
||||
}
|
||||
@@ -352,13 +430,13 @@ public class LoaderCursor extends CursorWrapper {
|
||||
}
|
||||
|
||||
public void commitRestoredItems() {
|
||||
if (restoredRows.size() > 0) {
|
||||
if (mRestoredRows.size() > 0) {
|
||||
// Update restored items that no longer require special handling
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(LauncherSettings.Favorites.RESTORED, 0);
|
||||
values.put(Favorites.RESTORED, 0);
|
||||
mContext.getContentResolver().update(mContentUri, values,
|
||||
Utilities.createDbSelectionQuery(
|
||||
LauncherSettings.Favorites._ID, restoredRows), null);
|
||||
Favorites._ID, mRestoredRows), null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,8 +444,7 @@ public class LoaderCursor extends CursorWrapper {
|
||||
* Returns true is the item is on workspace or hotseat
|
||||
*/
|
||||
public boolean isOnWorkspaceOrHotseat() {
|
||||
return container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
|
||||
container == LauncherSettings.Favorites.CONTAINER_HOTSEAT;
|
||||
return container == Favorites.CONTAINER_DESKTOP || container == Favorites.CONTAINER_HOTSEAT;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,9 +458,9 @@ public class LoaderCursor extends CursorWrapper {
|
||||
public void applyCommonProperties(ItemInfo info) {
|
||||
info.id = id;
|
||||
info.container = container;
|
||||
info.screenId = getInt(screenIndex);
|
||||
info.cellX = getInt(cellXIndex);
|
||||
info.cellY = getInt(cellYIndex);
|
||||
info.screenId = getInt(mScreenIndex);
|
||||
info.cellX = getInt(mCellXIndex);
|
||||
info.cellY = getInt(mCellYIndex);
|
||||
}
|
||||
|
||||
public void checkAndAddItem(ItemInfo info, BgDataModel dataModel) {
|
||||
@@ -396,7 +473,7 @@ public class LoaderCursor extends CursorWrapper {
|
||||
*/
|
||||
public void checkAndAddItem(
|
||||
ItemInfo info, BgDataModel dataModel, LoaderMemoryLogger logger) {
|
||||
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
if (info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
// Ensure that it is a valid intent. An exception here will
|
||||
// cause the item loading to get skipped
|
||||
ShortcutKey.fromItemInfo(info);
|
||||
@@ -413,9 +490,9 @@ public class LoaderCursor extends CursorWrapper {
|
||||
*/
|
||||
protected boolean checkItemPlacement(ItemInfo item) {
|
||||
int containerIndex = item.screenId;
|
||||
if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
|
||||
if (item.container == Favorites.CONTAINER_HOTSEAT) {
|
||||
final GridOccupancy hotseatOccupancy =
|
||||
occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT);
|
||||
mOccupied.get(Favorites.CONTAINER_HOTSEAT);
|
||||
|
||||
if (item.screenId >= mIDP.numDatabaseHotseatIcons) {
|
||||
Log.e(TAG, "Error loading shortcut " + item
|
||||
@@ -438,19 +515,18 @@ public class LoaderCursor extends CursorWrapper {
|
||||
} else {
|
||||
final GridOccupancy occupancy = new GridOccupancy(mIDP.numDatabaseHotseatIcons, 1);
|
||||
occupancy.cells[item.screenId][0] = true;
|
||||
occupied.put(LauncherSettings.Favorites.CONTAINER_HOTSEAT, occupancy);
|
||||
mOccupied.put(Favorites.CONTAINER_HOTSEAT, occupancy);
|
||||
return true;
|
||||
}
|
||||
} else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
||||
} else if (item.container != Favorites.CONTAINER_DESKTOP) {
|
||||
// Skip further checking if it is not the hotseat or workspace container
|
||||
return true;
|
||||
}
|
||||
|
||||
final int countX = mIDP.numColumns;
|
||||
final int countY = mIDP.numRows;
|
||||
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
|
||||
item.cellX < 0 || item.cellY < 0 ||
|
||||
item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
|
||||
if (item.container == Favorites.CONTAINER_DESKTOP && item.cellX < 0 || item.cellY < 0
|
||||
|| item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
|
||||
Log.e(TAG, "Error loading shortcut " + item
|
||||
+ " into cell (" + containerIndex + "-" + item.screenId + ":"
|
||||
+ item.cellX + "," + item.cellY
|
||||
@@ -458,7 +534,7 @@ public class LoaderCursor extends CursorWrapper {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!occupied.containsKey(item.screenId)) {
|
||||
if (!mOccupied.containsKey(item.screenId)) {
|
||||
GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1);
|
||||
if (item.screenId == Workspace.FIRST_SCREEN_ID && FeatureFlags.QSB_ON_FIRST_SCREEN) {
|
||||
// Mark the first X columns (X is width of the search container) in the first row as
|
||||
@@ -468,9 +544,9 @@ public class LoaderCursor extends CursorWrapper {
|
||||
int spanY = 1;
|
||||
screen.markCells(0, 0, spanX, spanY, true);
|
||||
}
|
||||
occupied.put(item.screenId, screen);
|
||||
mOccupied.put(item.screenId, screen);
|
||||
}
|
||||
final GridOccupancy occupancy = occupied.get(item.screenId);
|
||||
final GridOccupancy occupancy = mOccupied.get(item.screenId);
|
||||
|
||||
// Check if any workspace icons overlap with each other
|
||||
if (occupancy.isRegionVacant(item.cellX, item.cellY, item.spanX, item.spanY)) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -80,10 +80,29 @@ public class ModelDelegate implements ResourceBasedOverride {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load delegate items if any in the data model
|
||||
* Load hot seat items if any in the data model
|
||||
*/
|
||||
@WorkerThread
|
||||
public void loadItems(UserManagerState ums, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
|
||||
public void loadHotseatItems(UserManagerState ums,
|
||||
Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
|
||||
|
||||
/**
|
||||
* Load all apps items if any in the data model
|
||||
*/
|
||||
@WorkerThread
|
||||
public void loadAllAppsItems(UserManagerState ums,
|
||||
Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
|
||||
|
||||
/**
|
||||
* Load widget recommendation items if any in the data model
|
||||
*/
|
||||
@WorkerThread
|
||||
public void loadWidgetsRecommendationItems() { }
|
||||
|
||||
/**
|
||||
* Marks the ModelDelegate as active
|
||||
*/
|
||||
public void markActive() { }
|
||||
|
||||
/**
|
||||
* Load String cache
|
||||
|
||||
@@ -208,6 +208,11 @@ public class TestInformationHandler implements ResourceBasedOverride {
|
||||
);
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_WORKSPACE_CURRENT_PAGE_INDEX: {
|
||||
return getLauncherUIProperty(Bundle::putInt,
|
||||
launcher -> launcher.getWorkspace().getCurrentPage());
|
||||
}
|
||||
|
||||
case TestProtocol.REQUEST_HOTSEAT_CELL_CENTER: {
|
||||
final HotseatCellCenterRequest request = extra.getParcelable(
|
||||
TestProtocol.TEST_INFO_REQUEST_FIELD);
|
||||
|
||||
@@ -126,6 +126,9 @@ public final class TestProtocol {
|
||||
public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center";
|
||||
public static final String REQUEST_WORKSPACE_COLUMNS_ROWS = "workspace-columns-rows";
|
||||
|
||||
public static final String REQUEST_WORKSPACE_CURRENT_PAGE_INDEX =
|
||||
"workspace-current-page-index";
|
||||
|
||||
public static final String REQUEST_HOTSEAT_CELL_CENTER = "hotseat-cell-center";
|
||||
|
||||
public static final String REQUEST_GET_FOCUSED_TASK_HEIGHT_FOR_TABLET =
|
||||
|
||||
@@ -114,6 +114,10 @@ public class ReorderWidgets extends AbstractLauncherUiTest {
|
||||
new FavoriteItemsTransaction(mTargetContext, this);
|
||||
transaction = buildWorkspaceFromBoards(testCase.mStart, transaction);
|
||||
transaction.commit();
|
||||
// resetLoaderState triggers the launcher to start loading the workspace which allows
|
||||
// waitForLauncherCondition to wait for that condition, otherwise the condition would
|
||||
// always be true and it wouldn't wait for the changes to be applied.
|
||||
resetLoaderState();
|
||||
waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
|
||||
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
|
||||
mainWidgetCellPos.getCellY());
|
||||
|
||||
@@ -18,6 +18,9 @@ package com.android.launcher3.model;
|
||||
|
||||
import static androidx.test.InstrumentationRegistry.getContext;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_ID;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_PROVIDER;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.APPWIDGET_SOURCE;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CELLX;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CELLY;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER;
|
||||
@@ -30,9 +33,13 @@ import static com.android.launcher3.LauncherSettings.Favorites.INTENT;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.OPTIONS;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.RANK;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.RESTORED;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.SCREEN;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.SPANX;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.SPANY;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.TITLE;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites._ID;
|
||||
import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
|
||||
@@ -92,7 +99,9 @@ public class LoaderCursorTest {
|
||||
mCursor = new MatrixCursor(new String[] {
|
||||
ICON, ICON_PACKAGE, ICON_RESOURCE, TITLE,
|
||||
_ID, CONTAINER, ITEM_TYPE, PROFILE_ID,
|
||||
SCREEN, CELLX, CELLY, RESTORED, INTENT
|
||||
SCREEN, CELLX, CELLY, RESTORED, INTENT,
|
||||
APPWIDGET_ID, APPWIDGET_PROVIDER, SPANX,
|
||||
SPANY, RANK, OPTIONS, APPWIDGET_SOURCE
|
||||
});
|
||||
|
||||
UserManagerState ums = new UserManagerState();
|
||||
|
||||
@@ -67,6 +67,7 @@ public final class Workspace extends Home {
|
||||
"Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_W"
|
||||
+ ".*?metaState=META_CTRL_ON");
|
||||
static final Pattern LONG_CLICK_EVENT = Pattern.compile("onWorkspaceItemLongClick");
|
||||
public static final int MAX_WORKSPACE_DRAG_TRIES = 100;
|
||||
|
||||
private final UiObject2 mHotseat;
|
||||
|
||||
@@ -430,6 +431,12 @@ public final class Workspace extends Home {
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
}
|
||||
|
||||
/** Returns the index of the current page */
|
||||
static int geCurrentPage(LauncherInstrumentation launcher) {
|
||||
return launcher.getTestInfo(TestProtocol.REQUEST_WORKSPACE_CURRENT_PAGE_INDEX).getInt(
|
||||
TestProtocol.TEST_INFO_RESPONSE_FIELD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds folder icons in the current workspace.
|
||||
*
|
||||
@@ -569,21 +576,10 @@ public final class Workspace extends Home {
|
||||
expectLongClickEvents,
|
||||
/* runToSpringLoadedState= */ true);
|
||||
Point targetDest = getCellCenter(launcher, cellX, cellY, spanX, spanY);
|
||||
int displayX = launcher.getRealDisplaySize().x;
|
||||
|
||||
// Since the destination can be on another page, we need to drag to the edge first
|
||||
// until we reach the target page
|
||||
for (int i = 0; i < destinationWorkspace; i++) {
|
||||
// Don't drag all the way to the edge to prevent touch events from getting out of
|
||||
//screen bounds.
|
||||
Point screenEdge = new Point(displayX - 1, targetDest.y);
|
||||
Point finalDragStart = dragStart;
|
||||
executeAndWaitForPageScroll(launcher,
|
||||
() -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
|
||||
true, downTime, downTime, true,
|
||||
LauncherInstrumentation.GestureScope.INSIDE));
|
||||
dragStart = screenEdge;
|
||||
}
|
||||
dragStart = dragToGivenWorkspace(launcher, dragStart, destinationWorkspace,
|
||||
targetDest.y);
|
||||
|
||||
// targetDest.x is now between 0 and displayX so we found the target page,
|
||||
// we just have to put move the icon to the destination and drop it
|
||||
@@ -595,6 +591,45 @@ public final class Workspace extends Home {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a drag that already started at currentPosition, drag the item to the given destination
|
||||
* index defined by destinationWorkspaceIndex.
|
||||
*
|
||||
* @param launcher
|
||||
* @param currentPosition
|
||||
* @param destinationWorkspaceIndex
|
||||
* @param y
|
||||
* @return the finishing position of the drag.
|
||||
*/
|
||||
static Point dragToGivenWorkspace(LauncherInstrumentation launcher, Point currentPosition,
|
||||
int destinationWorkspaceIndex, int y) {
|
||||
final long downTime = SystemClock.uptimeMillis();
|
||||
int displayX = launcher.getRealDisplaySize().x;
|
||||
int currentPage = Workspace.geCurrentPage(launcher);
|
||||
int counter = 0;
|
||||
while (currentPage != destinationWorkspaceIndex) {
|
||||
counter++;
|
||||
if (counter > MAX_WORKSPACE_DRAG_TRIES) {
|
||||
throw new RuntimeException(
|
||||
"Wrong destination workspace index " + destinationWorkspaceIndex
|
||||
+ ", desired workspace was never reached");
|
||||
}
|
||||
// if the destination is greater than current page, set the display edge to be the
|
||||
// right edge. Don't drag all the way to the edge to prevent touch events from
|
||||
// getting out of screen bounds.
|
||||
int displayEdge = destinationWorkspaceIndex > currentPage ? displayX - 1 : 1;
|
||||
Point screenEdge = new Point(displayEdge, y);
|
||||
Point finalDragStart = currentPosition;
|
||||
executeAndWaitForPageScroll(launcher,
|
||||
() -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
|
||||
true, downTime, downTime, true,
|
||||
LauncherInstrumentation.GestureScope.INSIDE));
|
||||
currentPage = Workspace.geCurrentPage(launcher);
|
||||
currentPosition = screenEdge;
|
||||
}
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
private static void executeAndWaitForPageScroll(LauncherInstrumentation launcher,
|
||||
Runnable command) {
|
||||
launcher.executeAndWaitForEvent(command,
|
||||
|
||||
Reference in New Issue
Block a user