Merge "Enable new open app transitions when in multiwindow mode." into ub-launcher3-edmonton
diff --git a/proguard.flags b/proguard.flags
index e9f6db4..555d13e 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -120,6 +120,12 @@
*;
}
+# Discovery bounce animation
+-keep class com.android.launcher3.allapps.DiscoveryBounce$VerticalProgressWrapper {
+ public void setProgress(float);
+ public float getProgress();
+}
+
# BUG(70852369): Surpress additional warnings after changing from Proguard to R8
-dontwarn android.app.**
-dontwarn android.view.**
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index 065663d..cab20a3 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -155,6 +155,7 @@
CONFIRM = 4; // Indicates thata confirmation screen was accepted
STOP = 5; // Indicates onStop() was called (screen time out, power off)
RECENTS_BUTTON = 6; // Indicates that Recents button was pressed
+ RESUME = 7; // Indicates onResume() was called
}
optional Type type = 1;
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 429f3a2..f163872 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -13,9 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.quickstep.views.TaskView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.quickstep.views.TaskView
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:focusable="false"
android:elevation="4dp">
<com.android.quickstep.views.TaskThumbnailView
@@ -29,5 +31,6 @@
android:layout_width="@dimen/task_thumbnail_icon_size"
android:layout_height="@dimen/task_thumbnail_icon_size"
android:importantForAccessibility="no"
+ android:focusable="false"
android:layout_gravity="top|center_horizontal" />
</com.android.quickstep.views.TaskView>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java b/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
new file mode 100644
index 0000000..2e6dcc0
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/BackButtonAlphaHandler.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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 android.animation.ValueAnimator;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.quickstep.OverviewInteractionState;
+
+public class BackButtonAlphaHandler implements LauncherStateManager.StateHandler {
+
+ private static final String TAG = "BackButtonAlphaHandler";
+
+ private final Launcher mLauncher;
+ private final OverviewInteractionState mOverviewInteractionState;
+
+ public BackButtonAlphaHandler(Launcher launcher) {
+ mLauncher = launcher;
+ mOverviewInteractionState = OverviewInteractionState.getInstance(mLauncher);
+ }
+
+ @Override
+ public void setState(LauncherState state) {
+ UiFactory.onLauncherStateOrFocusChanged(mLauncher);
+ }
+
+ @Override
+ public void setStateWithAnimation(LauncherState toState,
+ AnimatorSetBuilder builder, LauncherStateManager.AnimationConfig config) {
+ if (!config.playNonAtomicComponent()) {
+ return;
+ }
+ float fromAlpha = mOverviewInteractionState.getBackButtonAlpha();
+ float toAlpha = toState.hideBackButton ? 0 : 1;
+ if (Float.compare(fromAlpha, toAlpha) != 0) {
+ ValueAnimator anim = ValueAnimator.ofFloat(fromAlpha, toAlpha);
+ anim.setDuration(config.duration);
+ anim.addUpdateListener(valueAnimator -> {
+ final float alpha = (float) valueAnimator.getAnimatedValue();
+ mOverviewInteractionState.setBackButtonAlpha(alpha, false);
+ });
+ builder.play(anim);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
index 3a49294..0116a8e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java
@@ -100,9 +100,9 @@
@Override
public int getVisibleElements(Launcher launcher) {
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- return 0;
+ return VERTICAL_SWIPE_INDICATOR;
} else {
- return HOTSEAT_SEARCH_BOX |
+ return HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR |
(launcher.getAppsView().getFloatingHeaderView().hasVisibleContent()
? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS);
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index b371677..76820b6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -78,11 +78,13 @@
}
public static StateHandler[] getStateHandler(Launcher launcher) {
- return new StateHandler[] {
- launcher.getAllAppsController(), launcher.getWorkspace(),
- new RecentsViewStateController(launcher)};
+ return new StateHandler[] {launcher.getAllAppsController(), launcher.getWorkspace(),
+ new RecentsViewStateController(launcher), new BackButtonAlphaHandler(launcher)};
}
+ /**
+ * Sets the back button visibility based on the current state/window focus.
+ */
public static void onLauncherStateOrFocusChanged(Launcher launcher) {
boolean shouldBackButtonBeHidden = launcher != null
&& launcher.getStateManager().getState().hideBackButton
@@ -96,10 +98,6 @@
.setBackButtonAlpha(shouldBackButtonBeHidden ? 0 : 1, true /* animate */);
}
- public static void setBackButtonAlpha(Launcher launcher, float alpha, boolean animate) {
- OverviewInteractionState.getInstance(launcher).setBackButtonAlpha(alpha,animate);
- }
-
public static void resetOverview(Launcher launcher) {
RecentsView recents = launcher.getOverviewPanel();
recents.reset();
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index d605746..922a7ff 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -91,6 +91,7 @@
// These are updated on the background thread
private ISystemUiProxy mISystemUiProxy;
private boolean mSwipeUpEnabled = true;
+ private float mBackButtonAlpha = 1;
private Runnable mOnSwipeUpSettingChangedListener;
@@ -117,7 +118,14 @@
return mSwipeUpEnabled;
}
+ public float getBackButtonAlpha() {
+ return mBackButtonAlpha;
+ }
+
public void setBackButtonAlpha(float alpha, boolean animate) {
+ if (!mSwipeUpEnabled) {
+ alpha = 1;
+ }
mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_ALPHA);
mUiHandler.obtainMessage(MSG_SET_BACK_BUTTON_ALPHA, animate ? 1 : 0, 0, alpha)
.sendToTarget();
@@ -128,6 +136,9 @@
}
private boolean handleUiMessage(Message msg) {
+ if (msg.what == MSG_SET_BACK_BUTTON_ALPHA) {
+ mBackButtonAlpha = (float) msg.obj;
+ }
mBgHandler.obtainMessage(msg.what, msg.arg1, msg.arg2, msg.obj).sendToTarget();
return true;
}
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 9e2de33..c5d74c7 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -20,8 +20,10 @@
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
@@ -71,4 +73,21 @@
// Just use the activity task size for multi-window as well.
return false;
}
+
+ @Override
+ public void addTaskAccessibilityActionsExtra(AccessibilityNodeInfo info) {
+ info.addAction(
+ new AccessibilityNodeInfo.AccessibilityAction(
+ R.string.recents_clear_all,
+ getContext().getText(R.string.recents_clear_all)));
+ }
+
+ @Override
+ public boolean performTaskAccessibilityActionExtra(int action) {
+ if (action == R.string.recents_clear_all) {
+ dismissAllTasks();
+ return true;
+ }
+ return false;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index d5c43a0..25e3dc6 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -19,6 +19,7 @@
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
@@ -43,4 +44,12 @@
}
return res;
}
+
+ @Override
+ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+ super.onFocusChanged(focused, direction, previouslyFocusedRect);
+ if (focused) {
+ mRecentsView.revealClearAllButton();
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 950f7fb..5aca4f3 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -35,6 +35,9 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
+import com.android.launcher3.R;
+import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.views.ScrimView;
import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils;
@@ -136,6 +139,12 @@
}
anim.play(ObjectAnimator.ofFloat(
mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen));
+
+ ObjectAnimator dragHandleAnim = ObjectAnimator.ofInt(
+ mActivity.findViewById(R.id.scrim_view), ScrimView.DRAG_HANDLE_ALPHA, 0);
+ dragHandleAnim.setInterpolator(Interpolators.ACCEL_2);
+ anim.play(dragHandleAnim);
+
return anim;
}
@@ -150,7 +159,7 @@
mActivity.getStateManager().goToState(NORMAL, false /* animate */);
} else {
LauncherState state = mActivity.getStateManager().getState();
- mActivity.getAllAppsController().setProgress(state.getVerticalProgress(mActivity));
+ mActivity.getAllAppsController().setState(state);
}
super.onTaskLaunched(success);
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index f038eff..829ed6c 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -41,6 +41,7 @@
import android.os.Build;
import android.os.Handler;
import android.os.UserHandle;
+import android.support.annotation.Nullable;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
@@ -53,7 +54,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
-import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
@@ -109,7 +110,6 @@
return recentsView.mAdjacentScale;
}
};
- public static final boolean FLIP_RECENTS = true;
private static final int DISMISS_TASK_DURATION = 300;
// The threshold at which we update the SystemUI flags when animating from the task into the app
private static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.6f;
@@ -267,10 +267,7 @@
mQuickScrubController = new QuickScrubController(mActivity, this);
mModel = RecentsModel.getInstance(context);
- mIsRtl = Utilities.isRtl(getResources());
- if (FLIP_RECENTS) {
- mIsRtl = !mIsRtl;
- }
+ mIsRtl = !Utilities.isRtl(getResources());
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
@@ -582,6 +579,11 @@
* and unloads the associated task data for tasks that are no longer visible.
*/
public void loadVisibleTaskData() {
+ if (!mOverviewStateEnabled) {
+ // Skip loading visible task data if we've already left the overview state
+ return;
+ }
+
RecentsTaskLoader loader = mModel.getRecentsTaskLoader();
int centerPageIndex = getPageNearestToCenterOfScreen();
int lower = Math.max(0, centerPageIndex - 2);
@@ -968,6 +970,13 @@
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_TAB:
+ if (!event.isAltPressed() &&
+ getNextPage() ==
+ (event.isShiftPressed() ? 0 : getChildCount() - 1)) {
+ // If not Alt-Tab navigation, don't loop forever in the carousel and leave
+ // it once we reached the end.
+ return false;
+ }
snapToPageRelative(event.isShiftPressed() ? -1 : 1);
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
@@ -993,6 +1002,22 @@
return super.dispatchKeyEvent(event);
}
+ @Override
+ protected void onFocusChanged(boolean gainFocus, int direction,
+ @Nullable Rect previouslyFocusedRect) {
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ if (gainFocus && getChildCount() > 0) {
+ switch (direction) {
+ case FOCUS_FORWARD:
+ setCurrentPage(0);
+ break;
+ case FOCUS_BACKWARD:
+ setCurrentPage(getChildCount() - 1);
+ break;
+ }
+ }
+ }
+
public void snapToTaskAfterNext() {
snapToPageRelative(1);
}
@@ -1002,6 +1027,7 @@
}
public void setContentAlpha(float alpha) {
+ alpha = Utilities.boundToRange(alpha, 0, 1);
mContentAlpha = alpha;
for (int i = getChildCount() - 1; i >= 0; i--) {
TaskView child = getPageAt(i);
@@ -1264,10 +1290,6 @@
@Override
protected void notifyPageSwitchListener(int prevPage) {
super.notifyPageSwitchListener(prevPage);
- View currChild = getChildAt(mCurrentPage);
- if (currChild != null) {
- currChild.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- }
loadVisibleTaskData();
}
@@ -1307,22 +1329,26 @@
}
public void revealClearAllButton() {
+ setCurrentPage(getChildCount() - 1); // Loads tasks info if needed.
scrollTo(mIsRtl ? 0 : computeMaxScrollX(), 0);
}
@Override
public void addChildrenForAccessibility(ArrayList<View> outChildren) {
- if (FLIP_RECENTS) {
- for (int i = getChildCount() - 1; i >= 0; --i) {
- outChildren.add(getChildAt(i));
- }
- } else {
- super.addChildrenForAccessibility(outChildren);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ outChildren.add(getChildAt(i));
}
}
@Override
protected boolean isPageOrderFlipped() {
- return FLIP_RECENTS;
+ return true;
+ }
+
+ public void addTaskAccessibilityActionsExtra(AccessibilityNodeInfo info) {
+ }
+
+ public boolean performTaskAccessibilityActionExtra(int action) {
+ return false;
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
index 429432b..846c28b 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java
@@ -23,12 +23,14 @@
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.FloatProperty;
-import android.view.Gravity;
import android.view.MotionEvent;
+import android.view.View;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.R;
+import java.util.ArrayList;
+
public class RecentsViewContainer extends InsettableFrameLayout {
public static final FloatProperty<RecentsViewContainer> CONTENT_ALPHA =
new FloatProperty<RecentsViewContainer>("contentAlpha") {
@@ -64,10 +66,6 @@
});
mRecentsView = findViewById(R.id.overview_panel);
- final InsettableFrameLayout.LayoutParams params =
- (InsettableFrameLayout.LayoutParams) mClearAllButton.getLayoutParams();
- params.gravity = Gravity.TOP | (RecentsView.FLIP_RECENTS ? Gravity.START : Gravity.END);
- mClearAllButton.setLayoutParams(params);
mClearAllButton.forceHasOverlappingRendering(false);
mRecentsView.setClearAllButton(mClearAllButton);
@@ -104,4 +102,11 @@
mRecentsView.setContentAlpha(alpha);
setVisibility(alpha > 0 ? VISIBLE : GONE);
}
+
+ @Override
+ public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
+ // Carousel is first in tab order.
+ views.add(mRecentsView);
+ views.add(mClearAllButton);
+ }
}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 24afd48..aca8351 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -154,15 +154,6 @@
}
@Override
- protected void updateDragHandleAlpha() {
- if (mDrawingFlatColor) {
- super.updateDragHandleAlpha();
- } else if (mDragHandle != null) {
- mDragHandle.setAlpha(255);
- }
- }
-
- @Override
protected void onDraw(Canvas canvas) {
float translate = drawBackground(canvas);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 744960c..0df0580 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -17,6 +17,7 @@
package com.android.quickstep.views;
import static android.widget.Toast.LENGTH_SHORT;
+
import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA_MULTIPLIER;
import android.animation.Animator;
@@ -116,7 +117,7 @@
}
launchTask(true /* animate */);
BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss(
- Touch.TAP, Direction.NONE, ((RecentsView) getParent()).indexOfChild(this),
+ Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
TaskUtils.getComponentKeyForTask(getTask().key));
});
setOutlineProvider(new TaskOutlineProvider(getResources()));
@@ -318,12 +319,14 @@
context.getText(menuOption.labelResId)));
}
}
+
+ getRecentsView().addTaskAccessibilityActionsExtra(info);
}
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == R.string.accessibility_close_task) {
- ((RecentsView) getParent()).dismissTask(this, true /*animateTaskView*/,
+ getRecentsView().dismissTask(this, true /*animateTaskView*/,
true /*removeTask*/);
return true;
}
@@ -339,9 +342,15 @@
}
}
+ if (getRecentsView().performTaskAccessibilityActionExtra(action)) return true;
+
return super.performAccessibilityAction(action, arguments);
}
+ private RecentsView getRecentsView() {
+ return (RecentsView) getParent();
+ }
+
public void notifyTaskLaunchFailed(String tag) {
String msg = "Failed to launch task";
if (mTask != null) {
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 5e7b117..02d793e 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -23,8 +23,7 @@
android:layout_height="match_parent"
android:clipChildren="true"
android:clipToPadding="false"
- android:focusable="true"
- android:focusableInTouchMode="true"
+ android:focusable="false"
android:saveEnabled="false" >
<include layout="@layout/all_apps_rv_layout" />
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 5a1c158..c75509e 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -101,10 +101,12 @@
}
public final void close(boolean animate) {
- animate &= !Utilities.isPowerSaverOn(getContext());
+ animate &= !Utilities.isPowerSaverPreventingAnimation(getContext());
+ if (mIsOpen) {
+ BaseActivity.fromContext(getContext()).getUserEventDispatcher()
+ .resetElapsedContainerMillis("container closed");
+ }
handleClose(animate);
- BaseActivity.fromContext(getContext()).getUserEventDispatcher()
- .resetElapsedContainerMillis("container closed");
mIsOpen = false;
}
@@ -121,9 +123,11 @@
protected abstract boolean isOfType(@FloatingViewType int type);
- public void onBackPressed() {
+ /** @return Whether the back is consumed. If false, Launcher will handle the back as well. */
+ public boolean onBackPressed() {
logActionCommand(Action.Command.BACK);
close(true);
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 7979082..6c2fd8e 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -1980,7 +1980,7 @@
// Animations are disabled in power save mode, causing the repeated animation to jump
// spastically between beginning and end states. Since this looks bad, we don't repeat
// the animation in power save mode.
- if (!Utilities.isPowerSaverOn(getContext())) {
+ if (!Utilities.isPowerSaverPreventingAnimation(getContext())) {
va.setRepeatMode(ValueAnimator.REVERSE);
va.setRepeatCount(ValueAnimator.INFINITE);
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 1e47431..bddcde3 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -50,6 +50,7 @@
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.Parcelable;
import android.os.Process;
import android.os.StrictMode;
@@ -243,6 +244,10 @@
private RotationHelper mRotationHelper;
+
+ private final Handler mHandler = new Handler();
+ private final Runnable mLogOnDelayedResume = this::logOnDelayedResume;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
if (DEBUG_STRICT_MODE) {
@@ -727,10 +732,11 @@
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onStop();
}
- mAppWidgetHost.setListenIfResumed(false);
-
getUserEventDispatcher().logActionCommand(Action.Command.STOP,
mStateManager.getState().containerType, -1);
+
+ mAppWidgetHost.setListenIfResumed(false);
+
NotificationListener.removeNotificationsChangedListener();
getStateManager().moveToRestState();
@@ -751,13 +757,23 @@
UiFactory.onStart(this);
}
+ private void logOnDelayedResume() {
+ if (hasBeenResumed()) {
+ getUserEventDispatcher().logActionCommand(Action.Command.RESUME,
+ mStateManager.getState().containerType, -1);
+ getUserEventDispatcher().startSession();
+ }
+ }
+
@Override
protected void onResume() {
TraceHelper.beginSection("ON_RESUME");
super.onResume();
TraceHelper.partitionSection("ON_RESUME", "superCall");
- getUserEventDispatcher().resetElapsedSessionMillis();
+ mHandler.removeCallbacks(mLogOnDelayedResume);
+ Utilities.postAsyncCallback(mHandler, mLogOnDelayedResume);
+
setOnResumeCallback(null);
// Process any items that were added while Launcher was away.
InstallShortcutReceiver.disableAndFlushInstallQueue(
@@ -1583,8 +1599,8 @@
// by using if-else statements.
UserEventDispatcher ued = getUserEventDispatcher();
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
- if (topView != null) {
- topView.onBackPressed();
+ if (topView != null && topView.onBackPressed()) {
+ // Handled by the floating view.
} else if (!isInState(NORMAL)) {
LauncherState lastState = mStateManager.getLastState();
ued.logActionCommand(Action.Command.BACK, mStateManager.getState().containerType,
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index fbe27b0..76681f2 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -51,6 +51,7 @@
public static final int ALL_APPS_HEADER = 1 << 2;
public static final int ALL_APPS_HEADER_EXTRA = 1 << 3; // e.g. app predictions
public static final int ALL_APPS_CONTENT = 1 << 4;
+ public static final int VERTICAL_SWIPE_INDICATOR = 1 << 5;
protected static final int FLAG_MULTI_PAGE = 1 << 0;
protected static final int FLAG_DISABLE_ACCESSIBILITY = 1 << 1;
@@ -201,9 +202,9 @@
public int getVisibleElements(Launcher launcher) {
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- return HOTSEAT_ICONS;
+ return HOTSEAT_ICONS | VERTICAL_SWIPE_INDICATOR;
}
- return HOTSEAT_ICONS | HOTSEAT_SEARCH_BOX;
+ return HOTSEAT_ICONS | HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR;
}
/**
diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java
index e6fc4c6..3fcdee9 100644
--- a/src/com/android/launcher3/LauncherStateManager.java
+++ b/src/com/android/launcher3/LauncherStateManager.java
@@ -396,7 +396,6 @@
setRestState(null);
}
- UiFactory.onLauncherStateOrFocusChanged(mLauncher);
UiFactory.onLauncherStateOrResumeChanged(mLauncher);
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 006dc95..4bd9a9b 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -39,7 +39,6 @@
import android.os.Message;
import android.os.PowerManager;
import android.os.TransactionTooLargeException;
-import android.support.v4.os.BuildCompat;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
@@ -83,7 +82,8 @@
private static final Matrix sMatrix = new Matrix();
private static final Matrix sInverseMatrix = new Matrix();
- public static final boolean ATLEAST_P = BuildCompat.isAtLeastP();
+ public static final boolean ATLEAST_P =
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.P;
public static final boolean ATLEAST_OREO_MR1 =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1;
@@ -492,7 +492,11 @@
LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE);
}
- public static boolean isPowerSaverOn(Context context) {
+ public static boolean isPowerSaverPreventingAnimation(Context context) {
+ if (ATLEAST_P) {
+ // Battery saver mode no longer prevents animations.
+ return false;
+ }
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
return powerManager.isPowerSaveMode();
}
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index b5c821a..ccd5586 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -4,6 +4,7 @@
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
@@ -25,11 +26,9 @@
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ScrimView;
@@ -184,13 +183,6 @@
anim.setDuration(config.duration);
anim.setInterpolator(builder.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
anim.addListener(getProgressAnimatorListener());
- if (toState.hideBackButton) {
- anim.addUpdateListener(animation -> {
- final float alpha = (float) animation.getAnimatedValue();
- UiFactory.setBackButtonAlpha(mLauncher, 1 - Utilities.boundToRange(alpha, 0, 1),
- false /* animate */);
- });
- }
builder.play(anim);
@@ -207,6 +199,9 @@
setter.setViewAlpha(mAppsView.getContentView(), hasContent ? 1 : 0, LINEAR);
setter.setViewAlpha(mAppsView.getScrollBar(), hasContent ? 1 : 0, LINEAR);
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra, hasContent, setter);
+
+ setter.setInt(mScrimView, ScrimView.DRAG_HANDLE_ALPHA,
+ (visibleElements & VERTICAL_SWIPE_INDICATOR) != 0 ? 255 : 0, LINEAR);
}
public AnimatorListenerAdapter getProgressAnimatorListener() {
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index deaf8d3..a0a79c8 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -24,14 +24,9 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
-import android.animation.Keyframe;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
import android.app.ActivityManager;
import android.os.Handler;
import android.view.MotionEvent;
-import android.view.animation.PathInterpolator;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
@@ -52,21 +47,21 @@
private final Launcher mLauncher;
private final Animator mDiscoBounceAnimation;
- public DiscoveryBounce(Launcher launcher, Animator animator) {
+ public DiscoveryBounce(Launcher launcher, float delta) {
super(launcher, null);
mLauncher = launcher;
-
- mDiscoBounceAnimation = animator;
AllAppsTransitionController controller = mLauncher.getAllAppsController();
- mDiscoBounceAnimation.setTarget(controller);
- mDiscoBounceAnimation.addListener(controller.getProgressAnimatorListener());
+ mDiscoBounceAnimation =
+ AnimatorInflater.loadAnimator(launcher, R.animator.discovery_bounce);
+ mDiscoBounceAnimation.setTarget(new VerticalProgressWrapper(controller, delta));
mDiscoBounceAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
handleClose(false);
}
});
+ mDiscoBounceAnimation.addListener(controller.getProgressAnimatorListener());
}
@Override
@@ -84,6 +79,14 @@
}
@Override
+ public boolean onBackPressed() {
+ super.onBackPressed();
+ // Go back to the previous state (from a user's perspective this floating view isn't
+ // something to go back from).
+ return false;
+ }
+
+ @Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
handleClose(false);
return false;
@@ -94,6 +97,9 @@
if (mIsOpen) {
mIsOpen = false;
mLauncher.getDragLayer().removeView(this);
+ // Reset the all-apps progress to what ever it was previously.
+ mLauncher.getAllAppsController().setProgress(mLauncher.getStateManager()
+ .getState().getVerticalProgress(mLauncher));
}
}
@@ -107,6 +113,12 @@
return (type & TYPE_ON_BOARD_POPUP) != 0;
}
+ private void show(int containerType) {
+ mIsOpen = true;
+ mLauncher.getDragLayer().addView(this);
+ mLauncher.getUserEventDispatcher().logActionBounceTip(containerType);
+ }
+
public static void showForHomeIfNeeded(Launcher launcher) {
showForHomeIfNeeded(launcher, true);
}
@@ -125,11 +137,7 @@
return;
}
- DiscoveryBounce view = new DiscoveryBounce(launcher,
- AnimatorInflater.loadAnimator(launcher, R.animator.discovery_bounce));
- view.mIsOpen = true;
- launcher.getDragLayer().addView(view);
- launcher.getUserEventDispatcher().logActionBounceTip(HOTSEAT);
+ new DiscoveryBounce(launcher, 0).show(HOTSEAT);
}
public static void showForOverviewIfNeeded(Launcher launcher) {
@@ -156,26 +164,29 @@
return;
}
- float verticalProgress = OVERVIEW.getVerticalProgress(launcher);
+ new DiscoveryBounce(launcher, (1 - OVERVIEW.getVerticalProgress(launcher)))
+ .show(PREDICTION);
+ }
- TimeInterpolator pathInterpolator = new PathInterpolator(0.35f, 0, 0.5f, 1);
- Keyframe keyframe3 = Keyframe.ofFloat(0.423f, verticalProgress - (1 - 0.9738f));
- keyframe3.setInterpolator(pathInterpolator);
- Keyframe keyframe4 = Keyframe.ofFloat(0.754f, verticalProgress);
- keyframe4.setInterpolator(pathInterpolator);
+ /**
+ * A wrapper around {@link AllAppsTransitionController} allowing a fixed shift in the value.
+ */
+ public static class VerticalProgressWrapper {
- PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("progress",
- Keyframe.ofFloat(0, verticalProgress),
- Keyframe.ofFloat(0.246f, verticalProgress), keyframe3, keyframe4,
- Keyframe.ofFloat(1f, verticalProgress));
- ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(null,
- new PropertyValuesHolder[]{propertyValuesHolder});
- animator.setDuration(2166);
- animator.setRepeatCount(5);
+ private final float mDelta;
+ private final AllAppsTransitionController mController;
- DiscoveryBounce view = new DiscoveryBounce(launcher, animator);
- view.mIsOpen = true;
- launcher.getDragLayer().addView(view);
- launcher.getUserEventDispatcher().logActionBounceTip(PREDICTION);
+ private VerticalProgressWrapper(AllAppsTransitionController controller, float delta) {
+ mController = controller;
+ mDelta = delta;
+ }
+
+ public float getProgress() {
+ return mController.getProgress() + mDelta;
+ }
+
+ public void setProgress(float progress) {
+ mController.setProgress(progress - mDelta);
+ }
}
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVP.java b/src/com/android/launcher3/compat/UserManagerCompatVP.java
index 2e8a8eb..fa3902b 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVP.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVP.java
@@ -15,41 +15,20 @@
*/
package com.android.launcher3.compat;
+import android.annotation.TargetApi;
import android.content.Context;
+import android.os.Build;
import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Log;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
+@TargetApi(Build.VERSION_CODES.P)
public class UserManagerCompatVP extends UserManagerCompatVNMr1 {
- private static final String TAG = "UserManagerCompatVP";
-
- private Method mRequestQuietModeEnabled;
UserManagerCompatVP(Context context) {
super(context);
- // TODO: Replace it with proper API call once SDK is ready.
- try {
- mRequestQuietModeEnabled = UserManager.class.getDeclaredMethod(
- "requestQuietModeEnabled", boolean.class, UserHandle.class);
- } catch (NoSuchMethodException e) {
- Log.e(TAG, "requestQuietModeEnabled is not available", e);
- }
}
@Override
public boolean requestQuietModeEnabled(boolean enableQuietMode, UserHandle user) {
- if (mRequestQuietModeEnabled == null) {
- return false;
- }
- try {
- return (boolean)
- mRequestQuietModeEnabled.invoke(mUserManager, enableQuietMode, user);
- } catch (IllegalAccessException | InvocationTargetException e) {
- Log.e(TAG, "Failed to invoke mRequestQuietModeEnabled", e);
- }
- return false;
+ return mUserManager.requestQuietModeEnabled(enableQuietMode, user);
}
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index b49952f..6b13da7 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -1437,12 +1437,13 @@
}
@Override
- public void onBackPressed() {
+ public boolean onBackPressed() {
if (isEditingName()) {
mFolderName.dispatchBackKey();
} else {
super.onBackPressed();
}
+ return true;
}
@Override
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 3b5585b..f020d2d 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -360,16 +360,18 @@
.getShortcutIconDrawable(shortcutInfo, mFillResIconDpi);
IconCache cache = LauncherAppState.getInstance(mContext).getIconCache();
- Bitmap unbadgedBitmap = null;
+ final Bitmap unbadgedBitmap;
if (unbadgedDrawable != null) {
unbadgedBitmap = createScaledBitmapWithoutShadow(unbadgedDrawable, 0);
} else {
if (fallbackIconProvider != null) {
- unbadgedBitmap = fallbackIconProvider.get();
+ // Fallback icons are already badged and with appropriate shadow
+ Bitmap fullIcon = fallbackIconProvider.get();
+ if (fullIcon != null) {
+ return createIconBitmap(fullIcon);
+ }
}
- if (unbadgedBitmap == null) {
- unbadgedBitmap = cache.getDefaultIcon(Process.myUserHandle()).icon;
- }
+ unbadgedBitmap = cache.getDefaultIcon(Process.myUserHandle()).icon;
}
BitmapInfo result = new BitmapInfo();
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 850c948..1842e19 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -125,6 +125,7 @@
return null;
}
+ private boolean mSessionStarted;
private long mElapsedContainerMillis;
private long mElapsedSessionMillis;
private long mActionDurationMillis;
@@ -216,9 +217,11 @@
public void logActionCommand(int command, Target srcTarget, Target dstTarget) {
LauncherEvent event = newLauncherEvent(newCommandAction(command), srcTarget);
- if (command == Action.Command.STOP && mAppOrTaskLaunch) {
- // Prevent double logging by skipping STOP when app or task has been launched.
- return;
+ if (command == Action.Command.STOP) {
+ if (mAppOrTaskLaunch || !mSessionStarted) {
+ mSessionStarted = false;
+ return;
+ }
}
if (dstTarget != null) {
@@ -405,7 +408,8 @@
}
- public final void resetElapsedSessionMillis() {
+ public final void startSession() {
+ mSessionStarted = true;
mElapsedSessionMillis = SystemClock.uptimeMillis();
mElapsedContainerMillis = SystemClock.uptimeMillis();
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 0e68538..24382b7 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -42,7 +42,6 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
-import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -224,8 +223,6 @@
cancelAtomicComponentsController();
}
mProgressMultiplier = initCurrentAnimation(animComponents);
- mCurrentAnimation.getAnimationPlayer().addUpdateListener(animation ->
- setBackButtonAlphaWithProgress((float) animation.getAnimatedValue()));
mCurrentAnimation.dispatchOnStart();
return true;
}
@@ -284,7 +281,6 @@
mAtomicComponentsController.setPlayFraction(fraction - mAtomicComponentsStartProgress);
}
maybeUpdateAtomicAnim(mFromState, mToState, fraction);
- setBackButtonAlphaWithProgress(fraction);
}
/**
@@ -477,14 +473,6 @@
}
}
- private void setBackButtonAlphaWithProgress(float progress) {
- if (mFromState.hideBackButton ^ mToState.hideBackButton) {
- progress = Utilities.boundToRange(progress, 0, 1);
- final float alpha = mToState.hideBackButton ? 1 - progress : progress;
- UiFactory.setBackButtonAlpha(mLauncher, alpha, false /* animate */);
- }
- }
-
private void logReachedState(int logAction) {
// Transition complete. log the action
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 6bbce00..6e3ef07 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -45,6 +45,7 @@
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
import android.support.v4.widget.ExploreByTouchHelper;
import android.util.AttributeSet;
+import android.util.Property;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -73,6 +74,19 @@
public class ScrimView extends View implements Insettable, OnChangeListener,
AccessibilityStateChangeListener, StateListener {
+ public static final Property<ScrimView, Integer> DRAG_HANDLE_ALPHA =
+ new Property<ScrimView, Integer>(Integer.TYPE, "dragHandleAlpha") {
+
+ @Override
+ public Integer get(ScrimView scrimView) {
+ return scrimView.mDragHandleAlpha;
+ }
+
+ @Override
+ public void set(ScrimView scrimView, Integer value) {
+ scrimView.setDragHandleAlpha(value);
+ }
+ };
private static final int WALLPAPERS = R.string.wallpaper_button_text;
private static final int WIDGETS = R.string.widget_button_text;
private static final int SETTINGS = R.string.settings_button_text;
@@ -102,6 +116,8 @@
@Nullable
protected Drawable mDragHandle;
+ private int mDragHandleAlpha = 255;
+
public ScrimView(Context context, AttributeSet attrs) {
super(context, attrs);
mLauncher = Launcher.getLauncher(context);
@@ -118,6 +134,7 @@
ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
mAM = (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE);
+ setFocusable(false);
}
@NonNull
@@ -187,7 +204,17 @@
protected void updateDragHandleAlpha() {
if (mDragHandle != null) {
- mDragHandle.setAlpha(Math.round(255 * Utilities.boundToRange(mProgress, 0, 1)));
+ mDragHandle.setAlpha(mDragHandleAlpha);
+ }
+ }
+
+ private void setDragHandleAlpha(int alpha) {
+ if (alpha != mDragHandleAlpha) {
+ mDragHandleAlpha = alpha;
+ if (mDragHandle != null) {
+ mDragHandle.setAlpha(mDragHandleAlpha);
+ invalidate();
+ }
}
}