Merge "Track window rather than shelf when FeatureFlags.SWIPE_HOME = true" into ub-launcher3-master
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index d7c16e6..979096c 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -153,6 +153,15 @@
android:readPermission="${packageName}.permission.READ_SETTINGS" />
<!--
+ The content provider for exposing various launcher grid options.
+ TODO: Add proper permissions
+ -->
+ <provider
+ android:name="com.android.launcher3.graphics.GridOptionsProvider"
+ android:authorities="${packageName}.grid_control"
+ android:exported="true" />
+
+ <!--
The settings activity. To extend point settings_fragment_name to appropriate fragment class
-->
<activity
diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
new file mode 100644
index 0000000..f2c9455
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 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.uioverrides;
+
+import static android.view.View.VISIBLE;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+
+import android.view.View;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.uioverrides.RecentsViewStateController;
+import com.android.launcher3.util.TouchController;
+
+/**
+ * Provides recents-related {@link UiFactory} logic and classes.
+ */
+public final class RecentsUiFactory {
+
+ // Scale recents takes before animating in
+ private static final float RECENTS_PREPARE_SCALE = 1.33f;
+
+ private RecentsUiFactory() {}
+
+ /**
+ * Creates and returns a touch controller for swiping recents tasks.
+ *
+ * @param launcher the launcher activity
+ * @return the touch controller for recents tasks
+ */
+ public static TouchController createTaskSwipeController(Launcher launcher) {
+ // We leave all input handling to the view itself.
+ return null;
+ }
+
+ /**
+ * Creates and returns the controller responsible for recents view state transitions.
+ *
+ * @param launcher the launcher activity
+ * @return state handler for recents
+ */
+ public static StateHandler createRecentsViewStateController(Launcher launcher) {
+ //TODO Override RecentsViewStateController on low RAM.
+ return new RecentsViewStateController(launcher);
+ }
+
+ /**
+ * Prepare the recents view to animate in.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void prepareToShowRecents(Launcher launcher) {
+ View overview = launcher.getOverviewPanel();
+ if (overview.getVisibility() != VISIBLE) {
+ SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
+ }
+ }
+
+ /**
+ * Clean-up logic that occurs when recents is no longer in use/visible.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void resetRecents(Launcher launcher) {}
+
+ /**
+ * Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void onLauncherStateOrResumeChanged(Launcher launcher) {}
+}
diff --git a/quickstep/recents_ui_overrides/src/.keep b/quickstep/recents_ui_overrides/src/.keep
deleted file mode 100644
index e69de29..0000000
--- a/quickstep/recents_ui_overrides/src/.keep
+++ /dev/null
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
new file mode 100644
index 0000000..f18f43c
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 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.uioverrides;
+
+import static android.view.View.VISIBLE;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.LauncherState.OVERVIEW;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager.StateHandler;
+import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.util.TouchController;
+import com.android.quickstep.views.RecentsView;
+
+/**
+ * Provides recents-related {@link UiFactory} logic and classes.
+ */
+public final class RecentsUiFactory {
+
+ // Scale recents takes before animating in
+ private static final float RECENTS_PREPARE_SCALE = 1.33f;
+
+ private RecentsUiFactory() {}
+
+ /**
+ * Creates and returns a touch controller for swiping recents tasks.
+ *
+ * @param launcher the launcher activity
+ * @return the touch controller for recents tasks
+ */
+ public static TouchController createTaskSwipeController(Launcher launcher) {
+ return new LauncherTaskViewController(launcher);
+ }
+
+ /**
+ * Creates and returns the controller responsible for recents view state transitions.
+ *
+ * @param launcher the launcher activity
+ * @return state handler for recents
+ */
+ public static StateHandler createRecentsViewStateController(Launcher launcher) {
+ return new RecentsViewStateController(launcher);
+ }
+
+ /**
+ * Prepare the recents view to animate in.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void prepareToShowRecents(Launcher launcher) {
+ RecentsView overview = launcher.getOverviewPanel();
+ if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
+ SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
+ }
+ }
+
+ /**
+ * Clean-up logic that occurs when recents is no longer in use/visible.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void resetRecents(Launcher launcher) {
+ RecentsView recents = launcher.getOverviewPanel();
+ recents.reset();
+ }
+
+ /**
+ * Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
+ *
+ * @param launcher the launcher activity
+ */
+ public static void onLauncherStateOrResumeChanged(Launcher launcher) {
+ LauncherState state = launcher.getStateManager().getState();
+ if (state == NORMAL) {
+ launcher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(false);
+ }
+ }
+
+ private static final class LauncherTaskViewController extends
+ TaskViewTouchController<Launcher> {
+
+ LauncherTaskViewController(Launcher activity) {
+ super(activity);
+ }
+
+ @Override
+ protected boolean isRecentsInteractive() {
+ return mActivity.isInState(OVERVIEW);
+ }
+
+ @Override
+ protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) {
+ mActivity.getStateManager().setCurrentUserControlledAnimation(animController);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 46886c9..cb5152a 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -443,7 +443,16 @@
private void playIconAnimators(AnimatorSet appOpenAnimator, View v, Rect windowTargetBounds,
boolean toggleVisibility) {
final boolean isBubbleTextView = v instanceof BubbleTextView;
- mFloatingView = new View(mLauncher);
+ if (mFloatingView == null) {
+ mFloatingView = new View(mLauncher);
+ } else {
+ mFloatingView.setTranslationX(0);
+ mFloatingView.setTranslationY(0);
+ mFloatingView.setScaleX(1);
+ mFloatingView.setScaleY(1);
+ mFloatingView.setAlpha(1);
+ mFloatingView.setBackground(null);
+ }
if (isBubbleTextView && v.getTag() instanceof ItemInfoWithIcon ) {
// Create a copy of the app icon
mFloatingView.setBackground(DrawableFactory.INSTANCE.get(mLauncher)
@@ -481,19 +490,17 @@
: viewLocationLeft;
LayoutParams lp = new LayoutParams(rect.width(), rect.height());
lp.ignoreInsets = true;
- lp.setMarginStart(viewLocationStart);
+ lp.leftMargin = viewLocationStart;
lp.topMargin = viewLocationTop;
mFloatingView.setLayoutParams(lp);
// Set the properties here already to make sure they'are available when running the first
// animation frame.
- mFloatingView.setLeft(viewLocationLeft);
- mFloatingView.setTop(viewLocationTop);
- mFloatingView.setRight(viewLocationLeft + rect.width());
- mFloatingView.setBottom(viewLocationTop + rect.height());
+ mFloatingView.layout(viewLocationLeft, viewLocationTop,
+ viewLocationLeft + rect.width(), viewLocationTop + rect.height());
// Swap the two views in place.
- ((ViewGroup) mDragLayer.getParent()).addView(mFloatingView);
+ ((ViewGroup) mDragLayer.getParent()).getOverlay().add(mFloatingView);
if (toggleVisibility) {
v.setVisibility(View.INVISIBLE);
}
@@ -562,7 +569,7 @@
((BubbleTextView) v).setStayPressed(false);
}
v.setVisibility(View.VISIBLE);
- ((ViewGroup) mDragLayer.getParent()).removeView(mFloatingView);
+ ((ViewGroup) mDragLayer.getParent()).getOverlay().remove(mFloatingView);
}
});
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 8f1d46c..de6f7a7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_QUICKSTEP_PREVIEW;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
import android.graphics.Rect;
@@ -75,7 +76,11 @@
public void onStateEnabled(Launcher launcher) {
RecentsView rv = launcher.getOverviewPanel();
rv.setOverviewStateEnabled(true);
- AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ AbstractFloatingView.closeAllOpenViews(launcher);
+ } else {
+ AbstractFloatingView.closeAllOpenViewsExcept(launcher, TYPE_QUICKSTEP_PREVIEW);
+ }
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 0ef67c4..3aa6482 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,10 +16,8 @@
package com.android.launcher3.uioverrides;
-import static android.view.View.VISIBLE;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
@@ -41,7 +39,6 @@
import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.UiThreadHelper;
@@ -49,7 +46,6 @@
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
-import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -83,7 +79,11 @@
&& !launcher.getDeviceProfile().isVerticalBarLayout()) {
list.add(new StatusBarTouchController(launcher));
}
- list.add(new LauncherTaskViewController(launcher));
+ TouchController taskSwipeController =
+ RecentsUiFactory.createTaskSwipeController(launcher);
+ if (taskSwipeController != null) {
+ list.add(taskSwipeController);
+ }
return list.toArray(new TouchController[list.size()]);
}
@@ -93,7 +93,8 @@
public static StateHandler[] getStateHandler(Launcher launcher) {
return new StateHandler[] {launcher.getAllAppsController(), launcher.getWorkspace(),
- new RecentsViewStateController(launcher), new BackButtonAlphaHandler(launcher)};
+ RecentsUiFactory.createRecentsViewStateController(launcher),
+ new BackButtonAlphaHandler(launcher)};
}
/**
@@ -113,8 +114,7 @@
}
public static void resetOverview(Launcher launcher) {
- RecentsView recents = launcher.getOverviewPanel();
- recents.reset();
+ RecentsUiFactory.resetRecents(launcher);
}
public static void onCreate(Launcher launcher) {
@@ -186,9 +186,7 @@
visible ? 1 : 0, profile.hotseatBarSizePx);
}
- if (state == NORMAL) {
- launcher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(false);
- }
+ RecentsUiFactory.onLauncherStateOrResumeChanged(launcher);
}
public static void onTrimMemory(Context context, int level) {
@@ -242,26 +240,6 @@
}
public static void prepareToShowOverview(Launcher launcher) {
- RecentsView overview = launcher.getOverviewPanel();
- if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
- SCALE_PROPERTY.set(overview, 1.33f);
- }
- }
-
- private static class LauncherTaskViewController extends TaskViewTouchController<Launcher> {
-
- public LauncherTaskViewController(Launcher activity) {
- super(activity);
- }
-
- @Override
- protected boolean isRecentsInteractive() {
- return mActivity.isInState(OVERVIEW);
- }
-
- @Override
- protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) {
- mActivity.getStateManager().setCurrentUserControlledAnimation(animController);
- }
+ RecentsUiFactory.prepareToShowRecents(launcher);
}
}
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 1570520..1678f06 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -154,7 +154,7 @@
@Override
public LayoutListener createLayoutListener(Launcher activity) {
- return new LauncherLayoutListener(activity);
+ return LauncherLayoutListener.resetAndGet(activity);
}
@Override
diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
index 93f1ee6..9712eb3 100644
--- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
+++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java
@@ -383,9 +383,9 @@
// Deferred gesture, start the animation and gesture tracking once we pass the actual
// touch slop
startTouchTrackingForWindowAnimation(ev.getEventTime());
- mPassedInitialSlop = true;
- mStartDisplacement = getDisplacement(ev);
}
+ mPassedInitialSlop = true;
+ mStartDisplacement = getDisplacement(ev);
notifyGestureStarted();
}
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index 258e0e4..d7720ee 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -660,13 +660,13 @@
}
private void updateFinalShiftUi() {
- if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null) {
- if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null) {
mLayoutListener.open();
+ mLayoutListener.update(mCurrentShift.value > 1, mUiLongSwipeMode,
+ mClipAnimationHelper.getCurrentRectWithInsets(),
+ mClipAnimationHelper.getCurrentCornerRadius());
}
- mLayoutListener.update(mCurrentShift.value > 1, mUiLongSwipeMode,
- mClipAnimationHelper.getCurrentRectWithInsets(),
- mClipAnimationHelper.getCurrentCornerRadius());
}
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
index ea73e2c..84033cb 100644
--- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -16,6 +16,7 @@
package com.android.quickstep.util;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@@ -188,7 +189,7 @@
mTmpMatrix.setTranslate(app.position.x, app.position.y);
Rect crop = app.sourceContainerBounds;
float alpha = 1f;
- int layer;
+ int layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
float cornerRadius = 0f;
float scale = params.currentRect.width() / crop.width();
if (app.mode == targetSet.targetMode) {
@@ -201,8 +202,7 @@
mCurrentCornerRadius = cornerRadius;
}
alpha = mTaskAlphaCallback.apply(app, params.targetAlpha);
- layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
- } else {
+ } else if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
crop = null;
layer = Integer.MAX_VALUE;
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
index bcd3aee..a8205cd 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java
@@ -40,24 +40,44 @@
public class LauncherLayoutListener extends AbstractFloatingView
implements Insettable, LayoutListener {
+ public static LauncherLayoutListener resetAndGet(Launcher launcher) {
+ LauncherRecentsView lrv = launcher.getOverviewPanel();
+ LauncherLayoutListener listener = lrv.mLauncherLayoutListener;
+ if (listener.isOpen()) {
+ listener.close(false);
+ }
+ listener.setHandler(null);
+ return listener;
+ }
+
private final Launcher mLauncher;
private final Paint mPaint = new Paint();
private WindowTransformSwipeHandler mHandler;
private RectF mCurrentRect;
private float mCornerRadius;
- public LauncherLayoutListener(Launcher launcher) {
+ private boolean mWillNotDraw;
+
+ /**
+ * package private
+ */
+ LauncherLayoutListener(Launcher launcher) {
super(launcher, null);
mLauncher = launcher;
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
setLayoutParams(new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+
+ mWillNotDraw = willNotDraw();
+ super.setWillNotDraw(false);
}
@Override
public void update(boolean shouldFinish, boolean isLongSwipe, RectF currentRect,
float cornerRadius) {
- if (!ENABLE_QUICKSTEP_LIVE_TILE.get() && shouldFinish) {
- finish();
+ if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ if (shouldFinish) {
+ finish();
+ }
return;
}
@@ -69,6 +89,12 @@
}
@Override
+ public void setWillNotDraw(boolean willNotDraw) {
+ // Prevent super call as that causes additional relayout.
+ mWillNotDraw = willNotDraw;
+ }
+
+ @Override
public void setHandler(WindowTransformSwipeHandler handler) {
mHandler = handler;
}
@@ -125,6 +151,8 @@
@Override
protected void onDraw(Canvas canvas) {
- canvas.drawRoundRect(mCurrentRect, mCornerRadius, mCornerRadius, mPaint);
+ if (!mWillNotDraw) {
+ canvas.drawRoundRect(mCurrentRect, mCornerRadius, mCornerRadius, mPaint);
+ }
}
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 6396d1a..7389d65 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -35,6 +35,7 @@
import android.view.ViewDebug;
import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
@@ -70,6 +71,7 @@
private float mTranslationYFactor;
private final TransformParams mTransformParams = new TransformParams();
+ final LauncherLayoutListener mLauncherLayoutListener;
public LauncherRecentsView(Context context) {
this(context, null);
@@ -82,6 +84,7 @@
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setContentAlpha(0);
+ mLauncherLayoutListener = new LauncherLayoutListener(BaseActivity.fromContext(context));
}
@Override
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index e5bed54..0194b0b 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -116,8 +116,12 @@
mIsDarkTextTheme = Themes.getAttrBoolean(mActivity, R.attr.isWorkspaceDarkText);
}
- public void bind() {
+ public void bind(Task task) {
mOverlay.reset();
+ mTask = task;
+ int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
+ mPaint.setColor(color);
+ mBackgroundPaint.setColor(color);
}
/**
@@ -125,10 +129,6 @@
*/
public void setThumbnail(Task task, ThumbnailData thumbnailData) {
mTask = task;
- int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
- mPaint.setColor(color);
- mBackgroundPaint.setColor(color);
-
if (thumbnailData != null && thumbnailData.thumbnail != null) {
Bitmap bm = thumbnailData.thumbnail;
bm.prepareToDraw();
@@ -255,15 +255,14 @@
private void updateThumbnailPaintFilter() {
int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255);
+ ColorFilter filter = getColorFilter(mul, mIsDarkTextTheme, mSaturation);
+ mBackgroundPaint.setColorFilter(filter);
mDimmingPaintAfterClearing.setAlpha(255 - mul);
if (mBitmapShader != null) {
- ColorFilter filter = getColorFilter(mul, mIsDarkTextTheme, mSaturation);
mPaint.setColorFilter(filter);
- mBackgroundPaint.setColorFilter(filter);
} else {
mPaint.setColorFilter(null);
mPaint.setColor(Color.argb(255, mul, mul, mul));
- mBackgroundPaint.setColorFilter(null);
}
invalidate();
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 456a022..2946dfd 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -214,7 +214,7 @@
*/
public void bind(Task task) {
mTask = task;
- mSnapshotView.bind();
+ mSnapshotView.bind(task);
}
public Task getTask() {
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 3c0ef79..45bdea8 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -139,6 +139,13 @@
APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
}
+ public InvariantDeviceProfile(Context context, String gridName) {
+ String newName = initGrid(context, gridName);
+ if (newName == null || !newName.equals(gridName)) {
+ throw new IllegalArgumentException("Unknown grid name");
+ }
+ }
+
/**
* Retrieve system defined or RRO overriden icon shape.
*/
@@ -150,7 +157,7 @@
return context.getResources().getString(CONFIG_ICON_MASK_RES_ID);
}
- private void initGrid(Context context, String gridName) {
+ private String initGrid(Context context, String gridName) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
@@ -218,6 +225,7 @@
} else {
defaultWallpaperSize = new Point(Math.max(smallSide * 2, largeSide), largeSide);
}
+ return closestProfile.name;
}
@Nullable
@@ -441,11 +449,11 @@
}
- private static final class GridOption {
+ public static final class GridOption {
- private final String name;
- private final int numRows;
- private final int numColumns;
+ public final String name;
+ public final int numRows;
+ public final int numColumns;
private final int numFolderRows;
private final int numFolderColumns;
@@ -457,7 +465,7 @@
private final SparseArray<TypedValue> extraAttrs;
- GridOption(Context context, AttributeSet attrs) {
+ public GridOption(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.GridDisplayOption);
name = a.getString(R.styleable.GridDisplayOption_name);
diff --git a/src/com/android/launcher3/graphics/GridOptionsProvider.java b/src/com/android/launcher3/graphics/GridOptionsProvider.java
new file mode 100644
index 0000000..9b907ba
--- /dev/null
+++ b/src/com/android/launcher3/graphics/GridOptionsProvider.java
@@ -0,0 +1,157 @@
+package com.android.launcher3.graphics;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.res.XmlResourceParser;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.InvariantDeviceProfile.GridOption;
+import com.android.launcher3.R;
+import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.util.UiThreadHelper;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.Future;
+
+/**
+ * Exposes various launcher grid options and allows the caller to change them.
+ * APIs:
+ * /list_options: List the various available grip options, has following columns
+ * name: name of the grid
+ * rows: number of rows in the grid
+ * cols: number of columns in the grid
+ * preview_count: number of previews available for this grid option. The preview uri
+ * looks like /preview/<grid-name>/<preview index starting with 0>
+ * is_default: true if this grid is currently active
+ *
+ * /preview: Opens a file stream for the grid preview
+ */
+public class GridOptionsProvider extends ContentProvider {
+
+ private static final String TAG = "GridOptionsProvider";
+
+ private static final String KEY_NAME = "name";
+ private static final String KEY_ROWS = "rows";
+ private static final String KEY_COLS = "cols";
+ private static final String KEY_PREVIEW_COUNT = "preview_count";
+ private static final String KEY_IS_DEFAULT = "is_default";
+
+ private static final String KEY_PREVIEW = "preview";
+ private static final String MIME_TYPE_PNG = "image/png";
+
+ public static final PipeDataWriter<Future<Bitmap>> BITMAP_WRITER =
+ new PipeDataWriter<Future<Bitmap>>() {
+ @Override
+ public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String s,
+ Bundle bundle, Future<Bitmap> bitmap) {
+ try (AutoCloseOutputStream os = new AutoCloseOutputStream(output)) {
+ bitmap.get().compress(Bitmap.CompressFormat.PNG, 100, os);
+ } catch (Exception e) {
+ Log.w(TAG, "fail to write to pipe", e);
+ }
+ }
+ };
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ // TODO: Validate the query uri
+ MatrixCursor cursor = new MatrixCursor(new String[] {
+ KEY_NAME, KEY_ROWS, KEY_COLS, KEY_PREVIEW_COUNT, KEY_IS_DEFAULT});
+ InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(getContext());
+ try (XmlResourceParser parser = getContext().getResources().getXml(R.xml.device_profiles)) {
+ final int depth = parser.getDepth();
+ int type;
+ while (((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+ if ((type == XmlPullParser.START_TAG) && "grid-option".equals(parser.getName())) {
+ GridOption gridOption = new GridOption(
+ getContext(), Xml.asAttributeSet(parser));
+
+ cursor.newRow()
+ .add(KEY_NAME, gridOption.name)
+ .add(KEY_ROWS, gridOption.numRows)
+ .add(KEY_COLS, gridOption.numColumns)
+ .add(KEY_PREVIEW_COUNT, 1)
+ .add(KEY_IS_DEFAULT, idp.numColumns == gridOption.numColumns
+ && idp.numRows == gridOption.numRows);
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Error parsing device profile", e);
+ }
+
+ return cursor;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ List<String> segments = uri.getPathSegments();
+ if (segments.size() > 0 && KEY_PREVIEW.equals(segments.get(0))) {
+ return MIME_TYPE_PNG;
+ }
+ return "vnd.android.cursor.dir/launcher_grid";
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues initialValues) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ List<String> segments = uri.getPathSegments();
+ if (segments.size() < 2 || !KEY_PREVIEW.equals(segments.get(0))) {
+ throw new FileNotFoundException("Invalid preview url");
+ }
+ String profileName = segments.get(1);
+ if (TextUtils.isEmpty(profileName)) {
+ throw new FileNotFoundException("Invalid preview url");
+ }
+
+ InvariantDeviceProfile idp;
+ try {
+ idp = new InvariantDeviceProfile(getContext(), profileName);
+ } catch (Exception e) {
+ throw new FileNotFoundException(e.getMessage());
+ }
+
+ LooperExecutor executor = new LooperExecutor(UiThreadHelper.getBackgroundLooper());
+ try {
+ return openPipeHelper(uri, MIME_TYPE_PNG, null,
+ executor.submit(new LauncherPreviewRenderer(getContext(), idp)), BITMAP_WRITER);
+ } catch (Exception e) {
+ throw new FileNotFoundException(e.getMessage());
+ }
+ }
+}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index dc6f50f..e52fe66 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -61,6 +61,7 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
+import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
/**
@@ -72,7 +73,7 @@
* 4) Measure and draw the view on a canvas
*/
@TargetApi(Build.VERSION_CODES.O)
-public class LauncherPreviewRenderer {
+public class LauncherPreviewRenderer implements Callable<Bitmap> {
private static final String TAG = "LauncherPreviewRenderer";
@@ -110,7 +111,8 @@
context.getString(R.string.label_application);
}
- public Bitmap createScreenShot() {
+ @Override
+ public Bitmap call() {
return BitmapRenderer.createHardwareBitmap(mDp.widthPx, mDp.heightPx, c -> {
if (Looper.myLooper() == Looper.getMainLooper()) {
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 84fd908..82ea8be 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -54,7 +54,7 @@
@NonNull
public AppIcon getAppIcon(String appName) {
final UiObject2 allAppsContainer = verifyActiveContainer();
- final BySelector appIconSelector = AppIcon.getAppIconSelector(appName);
+ final BySelector appIconSelector = AppIcon.getAppIconSelector(appName, mLauncher);
if (!allAppsContainer.hasObject(appIconSelector)) {
scrollBackToBeginning();
int attempts = 0;
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index efefc0d..7582d53 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -31,8 +31,8 @@
super(launcher, icon);
}
- static BySelector getAppIconSelector(String appName) {
- return By.clazz(TextView.class).text(appName).pkg(LauncherInstrumentation.LAUNCHER_PKG);
+ static BySelector getAppIconSelector(String appName, LauncherInstrumentation launcher) {
+ return By.clazz(TextView.class).text(appName).pkg(launcher.mLauncherPackageName);
}
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 4fce211..5f60113 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -16,13 +16,13 @@
package com.android.launcher3.tapl;
-import java.util.Collections;
-import java.util.List;
-
import androidx.annotation.NonNull;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiObject2;
+import java.util.Collections;
+import java.util.List;
+
/**
* Common overview pane for both Launcher and fallback recents
*/
@@ -69,7 +69,7 @@
public OverviewTask getCurrentTask() {
verifyActiveContainer();
final List<UiObject2> taskViews = mLauncher.getDevice().findObjects(
- LauncherInstrumentation.getLauncherObjectSelector("snapshot"));
+ mLauncher.getLauncherObjectSelector("snapshot"));
LauncherInstrumentation.assertNotEquals("Unable to find a task", 0, taskViews.size());
// taskViews contains up to 3 task views: the 'main' (having the widest visible
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index bd1c657..7070555 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -83,13 +83,13 @@
private static final String APPS_RES_ID = "apps_view";
private static final String OVERVIEW_RES_ID = "overview_panel";
private static final String WIDGETS_RES_ID = "widgets_list_view";
- static final String LAUNCHER_PKG = "com.google.android.apps.nexuslauncher";
public static final int WAIT_TIME_MS = 60000;
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private static WeakReference<VisibleContainer> sActiveContainer = new WeakReference<>(null);
private final UiDevice mDevice;
+ final String mLauncherPackageName;
private final boolean mSwipeUpEnabled;
private Boolean mSwipeUpEnabledOverride = null;
private final Instrumentation mInstrumentation;
@@ -101,6 +101,7 @@
public LauncherInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
mDevice = UiDevice.getInstance(instrumentation);
+ mLauncherPackageName = mDevice.getLauncherPackageName();
final boolean swipeUpEnabledDefault =
!SwipeUpSetting.isSwipeUpSettingAvailable() ||
SwipeUpSetting.isSwipeUpEnabledDefaultValue();
@@ -379,14 +380,15 @@
@NonNull
UiObject2 waitForLauncherObject(String resName) {
- final UiObject2 object = mDevice.wait(Until.findObject(getLauncherObjectSelector(resName)),
- WAIT_TIME_MS);
- assertNotNull("Can't find a launcher object; id: " + resName, object);
+ final BySelector selector = getLauncherObjectSelector(resName);
+ final UiObject2 object = mDevice.wait(Until.findObject(selector), WAIT_TIME_MS);
+ assertNotNull("Can't find a launcher object; selector: " + selector + ", current launcher: "
+ + mDevice.getLauncherPackageName(), object);
return object;
}
- static BySelector getLauncherObjectSelector(String resName) {
- return By.res(LAUNCHER_PKG, resName);
+ BySelector getLauncherObjectSelector(String resName) {
+ return By.res(mLauncherPackageName, resName);
}
@NonNull
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index c45f0f0..5e6ad4d 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -69,7 +69,7 @@
@Nullable
public AppIcon tryGetWorkspaceAppIcon(String appName) {
final UiObject2 workspace = verifyActiveContainer();
- final UiObject2 icon = workspace.findObject(AppIcon.getAppIconSelector(appName));
+ final UiObject2 icon = workspace.findObject(AppIcon.getAppIconSelector(appName, mLauncher));
return icon != null ? new AppIcon(mLauncher, icon) : null;
}
@@ -85,7 +85,7 @@
return new AppIcon(mLauncher,
mLauncher.getObjectInContainer(
verifyActiveContainer(),
- AppIcon.getAppIconSelector(appName)));
+ AppIcon.getAppIconSelector(appName, mLauncher)));
}
/**
@@ -108,7 +108,7 @@
@NonNull
private AppIcon getHotseatAppIcon(String appName) {
return new AppIcon(mLauncher, mLauncher.getObjectInContainer(
- mHotseat, AppIcon.getAppIconSelector(appName)));
+ mHotseat, AppIcon.getAppIconSelector(appName, mLauncher)));
}
private void dragIconToNextScreen(AppIcon app, UiObject2 workspace) {