Merge "Ditch work profile orange and use the accent color instead" into ub-launcher3-master
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index bdc7c36..d8504f1 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -29,7 +29,7 @@
<dimen name="quickstep_fling_threshold_velocity">500dp</dimen>
<dimen name="quickstep_fling_min_velocity">250dp</dimen>
- <dimen name="workspace_overview_offset_x">-30dp</dimen>
+ <dimen name="workspace_overview_offset_x">-24dp</dimen>
<!-- TODO: This can be calculated using other resource values -->
<dimen name="all_apps_search_box_full_height">90dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 7433dfd..31c195d 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -421,8 +421,9 @@
Runnable finishedCallback) {
Handler handler = mLauncher.getWindow().getDecorView().getHandler();
postAtFrontOfQueueAsynchronously(handler, () -> {
- // We use a separate transition for Overview mode.
- if (mLauncher.isInState(LauncherState.OVERVIEW)) {
+ if (Utilities.getPrefs(mLauncher).getBoolean("pref_use_screenshot_animation",
+ true) && mLauncher.isInState(LauncherState.OVERVIEW)) {
+ // We use a separate transition for Overview mode.
setCurrentAnimator(null);
finishedCallback.run();
return;
@@ -470,14 +471,14 @@
float dX = getValue(0, endX, 0, 350, currentPlayTime,
Interpolators.AGGRESSIVE_EASE_IN_OUT);
+ float dY = (height - height * scale) / 2f;
TransactionCompat t = new TransactionCompat();
for (RemoteAnimationTargetCompat app : targets) {
if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) {
t.setAlpha(app.leash, 1f - percent);
-
- float dY = (height - (app.clipRect.height() * scale)) / 2f;
matrix.postTranslate(dX, dY);
+ matrix.postTranslate(app.position.x, app.position.y);
t.setMatrix(app.leash, matrix);
}
// TODO: Layer should be set only once, but there is possibly a race condition
diff --git a/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java b/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java
index 92a09dd..8533502 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/WorkspaceCard.java
@@ -76,7 +76,7 @@
mTranslateXPage0 = scale[1];
mTranslateXPage1 = OverviewState
.getScaleAndTranslationForPageRect(mLauncher,
- getResources().getDimension(R.dimen.workspace_overview_offset_x),
+ getResources().getDimension(R.dimen.workspace_overview_offset_x) / scale[0],
mTempRect)[1];
mExtraScrollShift = 0;
diff --git a/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java b/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java
index 0551938..aa210b8 100644
--- a/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java
+++ b/quickstep/src/com/android/quickstep/BaseSwipeInteractionHandler.java
@@ -15,6 +15,8 @@
*/
package com.android.quickstep;
+import android.support.annotation.WorkerThread;
+
import com.android.launcher3.states.InternalStateHandler;
import com.android.quickstep.TouchInteractionService.InteractionType;
@@ -28,8 +30,10 @@
public void reset() {}
+ @WorkerThread
public abstract void onGestureStarted();
+ @WorkerThread
public abstract void onGestureEnded(float endVelocity);
public abstract void updateInteractionType(@InteractionType int interactionType);
@@ -38,5 +42,6 @@
public abstract void onQuickScrubProgress(float progress);
+ @WorkerThread
public abstract void updateDisplacement(float displacement);
}
diff --git a/quickstep/src/com/android/quickstep/MotionEventQueue.java b/quickstep/src/com/android/quickstep/MotionEventQueue.java
index e3c3a1b..fae9b66 100644
--- a/quickstep/src/com/android/quickstep/MotionEventQueue.java
+++ b/quickstep/src/com/android/quickstep/MotionEventQueue.java
@@ -18,6 +18,8 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_MOVE;
+import android.annotation.TargetApi;
+import android.os.Build;
import android.view.Choreographer;
import android.view.MotionEvent;
@@ -29,25 +31,64 @@
/**
* Helper class for batching input events
*/
-public class MotionEventQueue implements Runnable {
+@TargetApi(Build.VERSION_CODES.O)
+public class MotionEventQueue {
+
+ private final EventArray mEmptyArray = new EventArray();
+ private final Object mExecutionLock = new Object();
// We use two arrays and swap the current index when one array is being consumed
private final EventArray[] mArrays = new EventArray[] {new EventArray(), new EventArray()};
private int mCurrentIndex = 0;
- private final Choreographer mChoreographer;
- private final Consumer<MotionEvent> mConsumer;
+ private final Runnable mMainFrameCallback = this::frameCallbackForMainChoreographer;
+ private final Runnable mInterimFrameCallback = this::frameCallbackForInterimChoreographer;
+
+ private final Choreographer mMainChoreographer;
+
+ private Consumer<MotionEvent> mConsumer;
+
+ private Choreographer mInterimChoreographer;
+ private Choreographer mCurrentChoreographer;
+
+ private Runnable mCurrentRunnable;
public MotionEventQueue(Choreographer choreographer, Consumer<MotionEvent> consumer) {
- mChoreographer = choreographer;
+ mMainChoreographer = choreographer;
mConsumer = consumer;
+
+ mCurrentChoreographer = mMainChoreographer;
+ mCurrentRunnable = mMainFrameCallback;
+ }
+
+ public void setConsumer(Consumer<MotionEvent> consumer) {
+ synchronized (mExecutionLock) {
+ mConsumer = consumer;
+ }
+ }
+
+ public void setInterimChoreographer(Choreographer choreographer) {
+ synchronized (mExecutionLock) {
+ synchronized (mArrays) {
+ mInterimChoreographer = choreographer;
+ if (choreographer == null) {
+ mCurrentChoreographer = mMainChoreographer;
+ mCurrentRunnable = mMainFrameCallback;
+ } else {
+ mCurrentChoreographer = mInterimChoreographer;
+ mCurrentRunnable = mInterimFrameCallback;
+ }
+
+ ChoreographerCompat.postInputFrame(mCurrentChoreographer, mCurrentRunnable);
+ }
+ }
}
public void queue(MotionEvent event) {
synchronized (mArrays) {
EventArray array = mArrays[mCurrentIndex];
if (array.isEmpty()) {
- ChoreographerCompat.postInputFrame(mChoreographer, this);
+ ChoreographerCompat.postInputFrame(mCurrentChoreographer, mCurrentRunnable);
}
int eventAction = event.getAction();
@@ -61,21 +102,33 @@
}
}
- @Override
- public void run() {
- EventArray array = swapAndGetCurrentArray();
- int size = array.size();
- for (int i = 0; i < size; i++) {
- MotionEvent event = array.get(i);
- mConsumer.accept(event);
- event.recycle();
- }
- array.clear();
- array.lastEventAction = ACTION_CANCEL;
+ private void frameCallbackForMainChoreographer() {
+ runFor(mMainChoreographer);
}
- private EventArray swapAndGetCurrentArray() {
+ private void frameCallbackForInterimChoreographer() {
+ runFor(mInterimChoreographer);
+ }
+
+ private void runFor(Choreographer caller) {
+ synchronized (mExecutionLock) {
+ EventArray array = swapAndGetCurrentArray(caller);
+ int size = array.size();
+ for (int i = 0; i < size; i++) {
+ MotionEvent event = array.get(i);
+ mConsumer.accept(event);
+ event.recycle();
+ }
+ array.clear();
+ array.lastEventAction = ACTION_CANCEL;
+ }
+ }
+
+ private EventArray swapAndGetCurrentArray(Choreographer caller) {
synchronized (mArrays) {
+ if (caller != mCurrentChoreographer) {
+ return mEmptyArray;
+ }
EventArray current = mArrays[mCurrentIndex];
mCurrentIndex = mCurrentIndex ^ 1;
return current;
diff --git a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
index 944804b..e2abd59 100644
--- a/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
+++ b/quickstep/src/com/android/quickstep/NavBarSwipeInteractionHandler.java
@@ -92,7 +92,7 @@
// animated to 1, so allow for a smooth transition.
private final AnimatedFloat mActivityMultiplier = new AnimatedFloat(this::updateFinalShift);
- private final Task mRunningTask;
+ private final int mRunningTaskId;
private final Context mContext;
private final MultiStateCallback mStateCallback;
@@ -116,13 +116,9 @@
NavBarSwipeInteractionHandler(RunningTaskInfo runningTaskInfo, Context context,
@InteractionType int interactionType) {
- // TODO: We need a better way for this
- TaskKey taskKey = new TaskKey(runningTaskInfo.id, 0, null, UserHandle.myUserId(), 0);
- mRunningTask = new Task(taskKey, null, null, "", "", Color.BLACK, Color.BLACK,
- true, false, false, false, null, 0, null, false);
-
mContext = context;
mInteractionType = interactionType;
+ mRunningTaskId = runningTaskInfo.id;
WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext);
@@ -192,7 +188,7 @@
launcher.setOnResumeCallback(this);
mLauncher = launcher;
mRecentsView = launcher.getOverviewPanel();
- mRecentsView.showTask(mRunningTask);
+ mRecentsView.showTask(mRunningTaskId);
mHotseat = mLauncher.getHotseat();
mWasLauncherAlreadyVisible = alreadyOnHome;
@@ -340,18 +336,15 @@
@UiThread
private void resumeLastTask() {
- // TODO: We need a better way for this
- TaskKey key = mRunningTask.key;
RecentsTaskLoadPlan loadPlan = RecentsModel.getInstance(mContext).getLastLoadPlan();
if (loadPlan != null) {
- Task task = loadPlan.getTaskStack().findTaskWithId(key.id);
+ Task task = loadPlan.getTaskStack().findTaskWithId(mRunningTaskId);
if (task != null) {
- key = task.key;
+ ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
+ ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(task.key, opts,
+ null, null);
}
}
-
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
- ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(key, opts, null, null);
}
public void reset() {
@@ -380,8 +373,7 @@
if (mInteractionType == INTERACTION_QUICK_SWITCH) {
for (int i = mRecentsView.getFirstTaskIndex(); i < mRecentsView.getPageCount(); i++) {
TaskView taskView = (TaskView) mRecentsView.getPageAt(i);
- // TODO: Match the keys directly
- if (taskView.getTask().key.id != mRunningTask.key.id) {
+ if (taskView.getTask().key.id != mRunningTaskId) {
mRecentsView.snapToPage(i, QUICK_SWITCH_SNAP_DURATION);
taskView.postDelayed(() -> {taskView.launchTask(true);},
QUICK_SWITCH_SNAP_DURATION);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
new file mode 100644
index 0000000..7c98317
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java
@@ -0,0 +1,65 @@
+/*
+ * 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.quickstep;
+
+import com.android.systemui.shared.system.BackgroundExecutor;
+import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+
+/**
+ * Wrapper around RecentsAnimationController to help with some synchronization
+ */
+public class RecentsAnimationWrapper {
+
+ public RecentsAnimationControllerCompat controller;
+ public RemoteAnimationTargetCompat[] targets;
+
+ private boolean mInputConsumerEnabled;
+
+ public synchronized void setController(
+ RecentsAnimationControllerCompat controller, RemoteAnimationTargetCompat[] targets) {
+ this.controller = controller;
+ this.targets = targets;
+
+ if (mInputConsumerEnabled) {
+ enableInputConsumer();
+ }
+ }
+
+ public void finish(boolean toHome) {
+ BackgroundExecutor.get().submit(() -> {
+ synchronized (this) {
+ if (controller != null) {
+ controller.setInputConsumerEnabled(false);
+ controller.finish(toHome);
+ }
+ }
+ });
+ }
+
+ public void enableInputConsumer() {
+ mInputConsumerEnabled = true;
+ if (mInputConsumerEnabled) {
+ BackgroundExecutor.get().submit(() -> {
+ synchronized (this) {
+ if (controller != null) {
+ controller.setInputConsumerEnabled(true);
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java
index 6937c1f..8e03f37 100644
--- a/quickstep/src/com/android/quickstep/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/RecentsView.java
@@ -98,7 +98,8 @@
private final RecentsModel mModel;
private int mLoadPlanId = -1;
- private Task mFirstTask;
+ // Only valid until the launcher state changes to NORMAL
+ private int mRunningTaskId = -1;
private Bitmap mScrim;
private Paint mFadePaint;
@@ -241,13 +242,6 @@
final ArrayList<Task> tasks = new ArrayList<>(stack.getTasks());
setLayoutTransition(null);
- if (mFirstTask != null) {
- // TODO: Handle this case here once we have a valid implementation for mFirstTask
- if (tasks.isEmpty() || !keysEquals(tasks.get(tasks.size() - 1), mFirstTask)) {
- // tasks.add(mFirstTask);
- }
- }
-
final int requiredChildCount = tasks.size() + mFirstTaskIndex;
for (int i = getChildCount(); i < requiredChildCount; i++) {
final TaskView taskView = (TaskView) inflater.inflate(R.layout.task, this, false);
@@ -394,7 +388,7 @@
}
public void reset() {
- mFirstTask = null;
+ mRunningTaskId = -1;
setCurrentPage(0);
}
@@ -407,11 +401,7 @@
*/
public void reloadIfNeeded() {
if (!mModel.isLoadPlanValid(mLoadPlanId)) {
- int taskId = -1;
- if (mFirstTask != null) {
- taskId = mFirstTask.key.id;
- }
- mLoadPlanId = mModel.loadTasks(taskId, this::applyLoadPlan);
+ mLoadPlanId = mModel.loadTasks(mRunningTaskId, this::applyLoadPlan);
}
}
@@ -423,41 +413,30 @@
* is called.
* Also scrolls the view to this task
*/
- public void showTask(Task task) {
+ public void showTask(int runningTaskId) {
boolean needsReload = false;
- boolean inflateFirstChild = true;
- if (getTaskCount() > 0) {
- TaskView tv = (TaskView) getChildAt(mFirstTaskIndex);
- inflateFirstChild = !keysEquals(tv.getTask(), task);
- }
- if (inflateFirstChild) {
+ if (getTaskCount() == 0) {
needsReload = true;
- setLayoutTransition(null);
// Add an empty view for now
+ setLayoutTransition(null);
final TaskView taskView = (TaskView) LayoutInflater.from(getContext())
.inflate(R.layout.task, this, false);
addView(taskView, mFirstTaskIndex);
- taskView.bind(task);
setLayoutTransition(mLayoutTransition);
}
if (!needsReload) {
needsReload = !mModel.isLoadPlanValid(mLoadPlanId);
}
if (needsReload) {
- mLoadPlanId = mModel.loadTasks(task.key.id, this::applyLoadPlan);
+ mLoadPlanId = mModel.loadTasks(runningTaskId, this::applyLoadPlan);
}
- mFirstTask = task;
+ mRunningTaskId = runningTaskId;
setCurrentPage(mFirstTaskIndex);
if (mCurrentPage >= mFirstTaskIndex) {
((TaskView) getPageAt(mCurrentPage)).setIconScale(0);
}
}
- private static boolean keysEquals(Task t1, Task t2) {
- // TODO: Match the keys directly
- return t1.key.id == t2.key.id;
- }
-
public QuickScrubController getQuickScrubController() {
return mQuickScrubController;
}
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index c0b12f7..0490832 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -40,6 +40,8 @@
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.support.annotation.IntDef;
import android.util.Log;
@@ -56,6 +58,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.Utilities;
+import com.android.launcher3.model.ModelPreload;
import com.android.launcher3.util.TraceHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -92,11 +95,16 @@
public static final int INTERACTION_QUICK_SWITCH = 1;
public static final int INTERACTION_QUICK_SCRUB = 2;
+ /**
+ * A background thread used for handling UI for another window.
+ */
+ private static HandlerThread sRemoteUiThread;
+
private final IBinder mMyBinder = new IOverviewProxy.Stub() {
@Override
public void onMotionEvent(MotionEvent ev) {
- mEventQueue.queue(ev);
+ onBinderMotionEvent(ev);
}
@Override
@@ -166,7 +174,8 @@
private Rect mStableInsets = new Rect();
private ISystemUiProxy mISystemUiProxy;
- private Consumer<MotionEvent> mCurrentConsumer = mNoOpTouchConsumer;
+
+ private Choreographer mBackgroundThreadChoreographer;
@Override
public void onCreate() {
@@ -184,8 +193,11 @@
// Clear the packageName as system can fail to dedupe it b/64108432
mHomeIntent.setComponent(mLauncher).setPackage(null);
- mEventQueue = new MotionEventQueue(Choreographer.getInstance(), this::handleMotionEvent);
+ mEventQueue = new MotionEventQueue(Choreographer.getInstance(), mNoOpTouchConsumer);
sConnected = true;
+
+ new ModelPreload().start(this);
+ initBackgroundChoreographer();
}
@Override
@@ -201,19 +213,23 @@
return mMyBinder;
}
- private void handleMotionEvent(MotionEvent ev) {
+ private void onBinderMotionEvent(MotionEvent ev) {
if (ev.getActionMasked() == ACTION_DOWN) {
mRunningTask = mAM.getRunningTask();
if (mRunningTask == null) {
- mCurrentConsumer = mNoOpTouchConsumer;
+ mEventQueue.setConsumer(mNoOpTouchConsumer);
+ mEventQueue.setInterimChoreographer(null);
} else if (mRunningTask.topActivity.equals(mLauncher)) {
- mCurrentConsumer = getLauncherConsumer();
+ mEventQueue.setConsumer(getLauncherConsumer());
+ mEventQueue.setInterimChoreographer(null);
} else {
- mCurrentConsumer = mOtherActivityTouchConsumer;
+ mEventQueue.setConsumer(mOtherActivityTouchConsumer);
+ mEventQueue.setInterimChoreographer(
+ isUsingScreenShot() ? null : mBackgroundThreadChoreographer);
}
}
- mCurrentConsumer.accept(ev);
+ mEventQueue.queue(ev);
}
private void handleTouchDownOnOtherActivity(MotionEvent ev) {
@@ -227,6 +243,19 @@
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
+ mTouchThresholdCrossed = false;
+
+ // Clean up the old interaction handler
+ if (mInteractionHandler != null) {
+ final BaseSwipeInteractionHandler handler = mInteractionHandler;
+ mMainThreadExecutor.execute(handler::reset);
+ mInteractionHandler = null;
+ }
+
+ // Start the window animation on down to give more time for launcher to draw
+ if (!isUsingScreenShot()) {
+ startTouchTrackingForWindowAnimation();
+ }
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
@@ -234,11 +263,6 @@
mVelocityTracker.clear();
}
mVelocityTracker.addMovement(ev);
- if (mInteractionHandler != null) {
- mInteractionHandler.reset();
- mInteractionHandler = null;
- }
- mTouchThresholdCrossed = false;
Display display = getSystemService(WindowManager.class).getDefaultDisplay();
mDisplayRotation = display.getRotation();
@@ -278,7 +302,11 @@
if (mTouchThresholdCrossed) {
mStartDisplacement = Math.signum(displacement) * mTouchSlop;
- startTouchTracking();
+ if (isUsingScreenShot()) {
+ startTouchTrackingForScreenshotAnimation();
+ }
+
+ // Notify the handler that the gesture has actually started
mInteractionHandler.onGestureStarted();
// Notify the system that we have started tracking the event
@@ -298,7 +326,7 @@
TraceHelper.endSection("TouchInt");
finishTouchTracking();
- mCurrentConsumer = mNoOpTouchConsumer;
+ mEventQueue.setConsumer(mNoOpTouchConsumer);
break;
}
}
@@ -312,72 +340,83 @@
return mDisplayRotation == Surface.ROTATION_270 && mStableInsets.left > 0;
}
+ private boolean isUsingScreenShot() {
+ return Utilities.getPrefs(this).getBoolean("pref_use_screenshot_animation", true);
+ }
+
/**
* Called when the gesture has started.
*/
- private void startTouchTracking() {
- if (Utilities.getPrefs(this).getBoolean("pref_use_screenshot_animation", true)) {
- // Create the shared handler
- final NavBarSwipeInteractionHandler handler =
- new NavBarSwipeInteractionHandler(mRunningTask, this, INTERACTION_NORMAL);
+ private void startTouchTrackingForScreenshotAnimation() {
+ // Create the shared handler
+ final NavBarSwipeInteractionHandler handler =
+ new NavBarSwipeInteractionHandler(mRunningTask, this, INTERACTION_NORMAL);
- TraceHelper.partitionSection("TouchInt", "Thershold crossed ");
+ TraceHelper.partitionSection("TouchInt", "Thershold crossed ");
- // Start the recents activity on a background thread
- BackgroundExecutor.get().submit(() -> {
- // Get the snap shot before
- handler.setTaskSnapshot(getCurrentTaskSnapshot());
+ // Start the recents activity on a background thread
+ BackgroundExecutor.get().submit(() -> {
+ // Get the snap shot before
+ handler.setTaskSnapshot(getCurrentTaskSnapshot());
- // Start the launcher activity with our custom handler
- Intent homeIntent = handler.addToIntent(new Intent(mHomeIntent));
- startActivity(homeIntent, ActivityOptions.makeCustomAnimation(this, 0, 0).toBundle());
- TraceHelper.partitionSection("TouchInt", "Home started");
- });
+ // Start the launcher activity with our custom handler
+ Intent homeIntent = handler.addToIntent(new Intent(mHomeIntent));
+ startActivity(homeIntent, ActivityOptions.makeCustomAnimation(this, 0, 0).toBundle());
+ TraceHelper.partitionSection("TouchInt", "Home started");
+ });
- // Preload the plan
- mRecentsModel.loadTasks(mRunningTask.id, null);
- mInteractionHandler = handler;
- mInteractionHandler.setGestureEndCallback(() -> mInteractionHandler = null);
- } else {
+ // Preload the plan
+ mRecentsModel.loadTasks(mRunningTask.id, null);
+ mInteractionHandler = handler;
+ mInteractionHandler.setGestureEndCallback(() -> mInteractionHandler = null);
+ }
- // Create the shared handler
- final WindowTransformSwipeHandler handler =
- new WindowTransformSwipeHandler(mRunningTask, this);
+ private void startTouchTrackingForWindowAnimation() {
+ // Create the shared handler
+ final WindowTransformSwipeHandler handler =
+ new WindowTransformSwipeHandler(mRunningTask, this);
+ BackgroundExecutor.get().submit(() -> {
+ ActivityManagerWrapper.getInstance().startRecentsActivity(mHomeIntent,
+ new AssistDataReceiver() {
+ @Override
+ public void onHandleAssistData(Bundle bundle) {
+ // Pass to AIAI
+ }
+ },
+ new RecentsAnimationListener() {
+ public void onAnimationStart(
+ RecentsAnimationControllerCompat controller,
+ RemoteAnimationTargetCompat[] apps) {
+ if (mInteractionHandler == handler) {
+ handler.setRecentsAnimation(controller, apps);
- BackgroundExecutor.get().submit(() -> {
- ActivityManagerWrapper.getInstance().startRecentsActivity(mHomeIntent,
- new AssistDataReceiver() {
- @Override
- public void onHandleAssistData(Bundle bundle) {
- // Pass to AIAI
+ } else {
+ controller.finish(false /* toHome */);
}
- },
- new RecentsAnimationListener() {
- public void onAnimationStart(
- RecentsAnimationControllerCompat controller,
- RemoteAnimationTargetCompat[] apps) {
- if (mInteractionHandler == handler) {
- handler.setRecentsAnimation(controller, apps);
+ }
- } else {
- controller.finish(false /* toHome */);
- }
+ public void onAnimationCanceled() {
+ if (mInteractionHandler == handler) {
+ handler.setRecentsAnimation(null, null);
}
+ }
+ }, null, null);
+ });
- public void onAnimationCanceled() {
- if (mInteractionHandler == handler) {
- handler.setRecentsAnimation(null, null);
- }
- }
- }, null, null);
- });
-
- // Preload the plan
- mRecentsModel.loadTasks(mRunningTask.id, null);
- mInteractionHandler = handler;
- mInteractionHandler.initWhenReady();
- mInteractionHandler.setGestureEndCallback(() -> mInteractionHandler = null);
- }
+ // Preload the plan
+ mRecentsModel.loadTasks(mRunningTask.id, null);
+ mInteractionHandler = handler;
+ handler.setGestureEndCallback(() -> {
+ if (handler == mInteractionHandler) {
+ mInteractionHandler = null;
+ }
+ });
+ handler.setLauncherOnDrawCallback(() -> {
+ if (handler == mInteractionHandler) {
+ mEventQueue.setInterimChoreographer(null);
+ }
+ });
+ mMainThreadExecutor.execute(handler::initWhenReady);
}
private void updateTouchTracking(@InteractionType int interactionType) {
@@ -398,6 +437,11 @@
: isNavBarOnLeft() ? -mVelocityTracker.getXVelocity(mActivePointerId)
: mVelocityTracker.getYVelocity(mActivePointerId);
mInteractionHandler.onGestureEnded(velocity);
+ } else if (!isUsingScreenShot()) {
+ // Since we start touch tracking on DOWN, we may reach this state without actually
+ // starting the gesture. In that case, just cleanup immediately.
+ final BaseSwipeInteractionHandler handler = mInteractionHandler;
+ mMainThreadExecutor.execute(handler::reset);
}
mVelocityTracker.recycle();
mVelocityTracker = null;
@@ -468,7 +512,7 @@
case ACTION_POINTER_UP:
case ACTION_POINTER_DOWN:
if (!mTrackingStarted) {
- mCurrentConsumer = mNoOpTouchConsumer;
+ mEventQueue.setConsumer(mNoOpTouchConsumer);
}
break;
case ACTION_MOVE: {
@@ -492,7 +536,7 @@
}
if (action == ACTION_UP || action == ACTION_CANCEL) {
- mCurrentConsumer = mNoOpTouchConsumer;
+ mEventQueue.setConsumer(mNoOpTouchConsumer);
}
}
@@ -506,6 +550,15 @@
}
}
+ private void initBackgroundChoreographer() {
+ if (sRemoteUiThread == null) {
+ sRemoteUiThread = new HandlerThread("remote-ui");
+ sRemoteUiThread.start();
+ }
+ new Handler(sRemoteUiThread.getLooper()).post(() ->
+ mBackgroundThreadChoreographer = Choreographer.getInstance());
+ }
+
public static boolean isInteractionQuick(@InteractionType int interactionType) {
return interactionType == INTERACTION_QUICK_SCRUB ||
interactionType == INTERACTION_QUICK_SWITCH;
diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
index e9b22a2..1351973 100644
--- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -15,8 +15,6 @@
*/
package com.android.quickstep;
-import static android.view.MotionEvent.ACTION_UP;
-
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.TouchInteractionService.INTERACTION_NORMAL;
@@ -33,33 +31,31 @@
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Build;
-import android.os.UserHandle;
+import android.os.Looper;
import android.support.annotation.UiThread;
+import android.support.annotation.WorkerThread;
import android.view.View;
+import android.view.ViewTreeObserver.OnDrawListener;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.states.InternalStateHandler;
import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.TouchInteractionService.InteractionType;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.system.BackgroundExecutor;
-import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
@@ -70,17 +66,18 @@
// Launcher UI related states
private static final int STATE_LAUNCHER_READY = 1 << 0;
- private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 1;
+ private static final int STATE_LAUNCHER_DRAWN = 1 << 1;
+ private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 2;
// Internal initialization states
- private static final int STATE_APP_CONTROLLER_RECEIVED = 1 << 2;
+ private static final int STATE_APP_CONTROLLER_RECEIVED = 1 << 3;
// Interaction finish states
- private static final int STATE_SCALED_SNAPSHOT_RECENTS = 1 << 3;
- private static final int STATE_SCALED_SNAPSHOT_APP = 1 << 4;
+ private static final int STATE_SCALED_SNAPSHOT_RECENTS = 1 << 4;
+ private static final int STATE_SCALED_SNAPSHOT_APP = 1 << 5;
private static final int LAUNCHER_UI_STATES =
- STATE_LAUNCHER_READY | STATE_ACTIVITY_MULTIPLIER_COMPLETE;
+ STATE_LAUNCHER_READY | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE;
private static final long MAX_SWIPE_DURATION = 200;
private static final long MIN_SWIPE_DURATION = 80;
@@ -103,8 +100,10 @@
// visible.
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
- private final Task mRunningTask;
+ private final MainThreadExecutor mMainExecutor = new MainThreadExecutor();
+
private final Context mContext;
+ private final int mRunningTaskId;
private MultiStateCallback mStateCallback;
private boolean mControllerStateAnimation;
@@ -115,6 +114,8 @@
private RecentsView mRecentsView;
private QuickScrubController mQuickScrubController;
+ private Runnable mLauncherDrawnCallback;
+
private boolean mWasLauncherAlreadyVisible;
private float mCurrentDisplacement;
@@ -122,28 +123,12 @@
private @InteractionType int mInteractionType = INTERACTION_NORMAL;
private boolean mStartedQuickScrubFromHome;
- private RecentsAnimationControllerCompat mRecentsAnimationController;
- private RemoteAnimationTargetCompat[] mRecentsAnimationApps;
- private boolean mRecentsAnimationInputConsumerEnabled;
+ private final RecentsAnimationWrapper mRecentsAnimationWrapper = new RecentsAnimationWrapper();
private Matrix mTmpMatrix = new Matrix();
- private final InputConsumerController mInputConsumerController;
- private final InputConsumerController.TouchListener mInputConsumerTouchListener =
- (ev) -> {
- if (ev.getActionMasked() == ACTION_UP) {
- onGestureInterruptEnd();
- }
- return true;
- };
-
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context) {
- // TODO: We need a better way for this
- TaskKey taskKey = new TaskKey(runningTaskInfo.id, 0, null, UserHandle.myUserId(), 0);
- mRunningTask = new Task(taskKey, null, null, "", "", Color.BLACK, Color.BLACK,
- true, false, false, false, null, 0, null, false);
mContext = context;
- mInputConsumerController = InputConsumerController.getRecentsAnimationInputConsumer();
-
+ mRunningTaskId = runningTaskInfo.id;
WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
@@ -173,6 +158,19 @@
this::reset);
mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_SCALED_SNAPSHOT_RECENTS,
this::reset);
+
+ mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_LAUNCHER_DRAWN,
+ mLauncherDrawnCallback);
+ }
+
+ private void setStateOnUiThread(int stateFlag) {
+ mMainExecutor.execute(() -> mStateCallback.setState(stateFlag));
+ }
+
+ public void setLauncherOnDrawCallback(Runnable callback) {
+ mLauncherDrawnCallback = callback;
+ mStateCallback.addCallback(STATE_LAUNCHER_READY | STATE_LAUNCHER_DRAWN,
+ mLauncherDrawnCallback);
}
private void initTransitionEndpoints(DeviceProfile dp) {
@@ -220,21 +218,39 @@
.createAnimationToNewWorkspace(OVERVIEW, accuracy);
mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
- mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE);
+ mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN);
} else {
+ TraceHelper.beginSection("WTS-init");
launcher.getStateManager().goToState(OVERVIEW, false);
+ TraceHelper.partitionSection("WTS-init", "State changed");
// TODO: Implement a better animation for fading in
View rootView = launcher.getRootView();
rootView.setAlpha(0);
- rootView.animate().alpha(1)
- .setDuration(getFadeInDuration())
- .withEndAction(() -> mStateCallback.setState(
- launcher == mLauncher ? STATE_ACTIVITY_MULTIPLIER_COMPLETE : 0));
+ rootView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
+
+ @Override
+ public void onDraw() {
+ TraceHelper.endSection("WTS-init", "Launcher frame is drawn");
+ rootView.post(() ->
+ rootView.getViewTreeObserver().removeOnDrawListener(this));
+ if (launcher != mLauncher) {
+ return;
+ }
+
+ if ((mStateCallback.getState() & STATE_LAUNCHER_DRAWN) == 0) {
+ mStateCallback.setState(STATE_LAUNCHER_DRAWN);
+ rootView.animate().alpha(1)
+ .setDuration(getFadeInDuration())
+ .withEndAction(() -> mStateCallback.setState(launcher == mLauncher
+ ? STATE_ACTIVITY_MULTIPLIER_COMPLETE : 0));
+ }
+ }
+ });
}
mRecentsView = mLauncher.getOverviewPanel();
- mRecentsView.showTask(mRunningTask);
+ mRecentsView.showTask(mRunningTaskId);
mWasLauncherAlreadyVisible = alreadyOnHome;
mLauncherLayoutListener = new LauncherLayoutListener(mLauncher, this);
mLauncher.getDragLayer().addView(mLauncherLayoutListener);
@@ -277,7 +293,7 @@
}
}
- @UiThread
+ @WorkerThread
public void updateDisplacement(float displacement) {
mCurrentDisplacement = displacement;
@@ -329,70 +345,60 @@
AnimatorPlaybackController.wrap(anim, mTransitionDragLength * 2);
mLauncherTransitionController.setPlayFraction(mCurrentShift.value);
}
-
- // In case the transition length changed (which should never happen, redo everything
- updateDisplacement(mCurrentDisplacement);
}
- @UiThread
+ @WorkerThread
private void updateFinalShift() {
if (mStartedQuickScrubFromHome) {
return;
}
float shift = mCurrentShift.value;
- mRectEvaluator.evaluate(shift, mSourceRect, mTargetRect);
- float scale = (float) mCurrentRect.width() / mSourceRect.width();
- if (mRecentsAnimationApps != null) {
- mClipRect.left = mSourceRect.left;
- mClipRect.top = (int) (mStableInsets.top * shift);
- mClipRect.bottom = (int) (mDp.heightPx - (mStableInsets.bottom * shift));
- mClipRect.right = mSourceRect.right;
- mTmpMatrix.setScale(scale, scale, 0, 0);
- mTmpMatrix.postTranslate(mCurrentRect.left - mStableInsets.left * scale * shift,
- mCurrentRect.top - mStableInsets.top * scale * shift);
- TransactionCompat transaction = new TransactionCompat();
- for (RemoteAnimationTargetCompat app : mRecentsAnimationApps) {
- if (app.mode == MODE_CLOSING) {
- transaction.setMatrix(app.leash, mTmpMatrix)
- .setWindowCrop(app.leash, mClipRect)
- .show(app.leash);
+ synchronized (mRecentsAnimationWrapper) {
+ if (mRecentsAnimationWrapper.controller != null) {
+ mRectEvaluator.evaluate(shift, mSourceRect, mTargetRect);
+ float scale = (float) mCurrentRect.width() / mSourceRect.width();
+
+ mClipRect.left = mSourceRect.left;
+ mClipRect.top = (int) (mStableInsets.top * shift);
+ mClipRect.bottom = (int) (mDp.heightPx - (mStableInsets.bottom * shift));
+ mClipRect.right = mSourceRect.right;
+
+ mTmpMatrix.setScale(scale, scale, 0, 0);
+ mTmpMatrix.postTranslate(mCurrentRect.left - mStableInsets.left * scale * shift,
+ mCurrentRect.top - mStableInsets.top * scale * shift);
+ TransactionCompat transaction = new TransactionCompat();
+ for (RemoteAnimationTargetCompat app : mRecentsAnimationWrapper.targets) {
+ if (app.mode == MODE_CLOSING) {
+ transaction.setMatrix(app.leash, mTmpMatrix)
+ .setWindowCrop(app.leash, mClipRect)
+ .show(app.leash);
+ }
}
+ transaction.apply();
}
- transaction.apply();
}
if (mLauncherTransitionController != null) {
- mLauncherTransitionController.setPlayFraction(shift);
+ if (Looper.getMainLooper() == Looper.myLooper()) {
+ mLauncherTransitionController.setPlayFraction(shift);
+ } else {
+ // The fling operation completed even before the launcher was drawn
+ mMainExecutor.execute(() -> mLauncherTransitionController.setPlayFraction(shift));
+ }
}
}
public void setRecentsAnimation(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] apps) {
- mRecentsAnimationController = controller;
- if (mRecentsAnimationInputConsumerEnabled) {
- BackgroundExecutor.get().submit(() ->
- mRecentsAnimationController.setInputConsumerEnabled(true));
- }
- mRecentsAnimationApps = apps;
- mStateCallback.setState(STATE_APP_CONTROLLER_RECEIVED);
+ mRecentsAnimationWrapper.setController(controller, apps);
+ setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
}
- public void onGestureStarted() {
- mInputConsumerController.unregisterInputConsumer();
- mInputConsumerController.registerInputConsumer();
- mInputConsumerController.setTouchListener(mInputConsumerTouchListener);
+ public void onGestureStarted() { }
- if (mRecentsAnimationController != null) {
- BackgroundExecutor.get().submit(() ->
- mRecentsAnimationController.setInputConsumerEnabled(true));
- } else {
- mRecentsAnimationInputConsumerEnabled = true;
- }
- }
-
- @UiThread
+ @WorkerThread
public void onGestureEnded(float endVelocity) {
Resources res = mContext.getResources();
float flingThreshold = res.getDimension(R.dimen.quickstep_fling_threshold_velocity);
@@ -415,18 +421,6 @@
}
}
- if (endShift == mCurrentShift.value) {
- mStateCallback.setState((Float.compare(mCurrentShift.value, 0) == 0)
- ? STATE_SCALED_SNAPSHOT_APP : STATE_SCALED_SNAPSHOT_RECENTS);
- } else {
- animateToProgress(endShift, duration);
- }
- }
-
- @UiThread
- public void onGestureInterruptEnd() {
- final float endShift = 0;
- final long duration = MAX_SWIPE_DURATION;
animateToProgress(endShift, duration);
}
@@ -437,7 +431,7 @@
anim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
- mStateCallback.setState((Float.compare(mCurrentShift.value, 0) == 0)
+ setStateOnUiThread((Float.compare(mCurrentShift.value, 0) == 0)
? STATE_SCALED_SNAPSHOT_APP : STATE_SCALED_SNAPSHOT_RECENTS);
}
});
@@ -446,12 +440,7 @@
@UiThread
private void resumeLastTask() {
- if (mRecentsAnimationController != null) {
- BackgroundExecutor.get().submit(() -> {
- mRecentsAnimationController.setInputConsumerEnabled(false);
- mRecentsAnimationController.finish(false /* toHome */);
- });
- }
+ mRecentsAnimationWrapper.finish(false /* toHome */);
}
public void reset() {
@@ -460,12 +449,13 @@
if (mGestureEndCallback != null) {
mGestureEndCallback.run();
}
- mInputConsumerController.unregisterInputConsumer();
- // TODO: These should be done as part of ActivityOptions#OnAnimationStarted
- mLauncher.getStateManager().reapplyState();
- mLauncher.setOnResumeCallback(() -> mLauncherLayoutListener.close(false));
- mLauncherTransitionController.setPlayFraction(1);
+ if (mLauncher != null) {
+ // TODO: These should be done as part of ActivityOptions#OnAnimationStarted
+ mLauncher.getStateManager().reapplyState();
+ mLauncher.setOnResumeCallback(() -> mLauncherLayoutListener.close(false));
+ mLauncherTransitionController.setPlayFraction(1);
+ }
clearReference();
}
@@ -485,7 +475,7 @@
for (int i = mRecentsView.getFirstTaskIndex(); i < mRecentsView.getPageCount(); i++) {
TaskView taskView = (TaskView) mRecentsView.getPageAt(i);
// TODO: Match the keys directly
- if (taskView.getTask().key.id != mRunningTask.key.id) {
+ if (taskView.getTask().key.id != mRunningTaskId) {
mRecentsView.snapToPage(i, QUICK_SWITCH_SNAP_DURATION);
taskView.postDelayed(() -> {taskView.launchTask(true);},
QUICK_SWITCH_SNAP_DURATION);
@@ -497,22 +487,21 @@
mQuickScrubController.snapToPageForCurrentQuickScrubSection();
}
} else {
- if (mRecentsAnimationController != null) {
- TransactionCompat transaction = new TransactionCompat();
- for (RemoteAnimationTargetCompat app : mRecentsAnimationApps) {
- if (app.mode == MODE_CLOSING) {
- // Update the screenshot of the task
- final ThumbnailData thumbnail =
- mRecentsAnimationController.screenshotTask(app.taskId);
- mRecentsView.updateThumbnail(app.taskId, thumbnail);
+ synchronized (mRecentsAnimationWrapper) {
+ if (mRecentsAnimationWrapper.controller != null) {
+ TransactionCompat transaction = new TransactionCompat();
+ for (RemoteAnimationTargetCompat app : mRecentsAnimationWrapper.targets) {
+ if (app.mode == MODE_CLOSING) {
+ // Update the screenshot of the task
+ final ThumbnailData thumbnail =
+ mRecentsAnimationWrapper.controller.screenshotTask(app.taskId);
+ mRecentsView.updateThumbnail(app.taskId, thumbnail);
+ }
}
+ transaction.apply();
}
- transaction.apply();
- BackgroundExecutor.get().submit(() -> {
- mRecentsAnimationController.setInputConsumerEnabled(false);
- mRecentsAnimationController.finish(true /* toHome */);
- });
}
+ mRecentsAnimationWrapper.finish(true /* toHome */);
}
}
diff --git a/res/layout/system_shortcut_icon_only.xml b/res/layout/system_shortcut_icon_only.xml
index c59cb53..b8b5b8c 100644
--- a/res/layout/system_shortcut_icon_only.xml
+++ b/res/layout/system_shortcut_icon_only.xml
@@ -20,5 +20,6 @@
android:layout_height="@dimen/system_shortcut_header_icon_touch_size"
android:background="?android:attr/selectableItemBackgroundBorderless"
android:tint="?android:attr/textColorHint"
+ android:tintMode="src_in"
android:padding="@dimen/system_shortcut_header_icon_padding"
android:theme="@style/PopupItem" />
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c1883b1..85443ed 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -408,9 +408,7 @@
mAppTransitionManager = Utilities.getOverrideObject(LauncherAppTransitionManager.class,
this, R.string.app_transition_manager_class);
- if (!isInMultiWindowModeCompat()) {
- mAppTransitionManager.registerRemoteAnimations();
- }
+ mAppTransitionManager.registerRemoteAnimations();
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 1b169f5..929606e 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -20,7 +20,6 @@
import static com.android.launcher3.config.FeatureFlags.IS_DOGFOOD_BUILD;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -40,21 +39,18 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.AddWorkspaceItemsTask;
+import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.CacheDataUpdatedTask;
-import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.LoaderResults;
import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.model.PackageInstallStateChangedTask;
-import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.model.PackageUpdatedTask;
import com.android.launcher3.model.ShortcutsChangedTask;
import com.android.launcher3.model.UserLockStateChangedTask;
-import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index dc3de18..338bdf3 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -538,7 +538,7 @@
public void onScrollUpEnd() {
if (mUsingTabs) {
- ((PersonalWorkSlidingTabStrip) findViewById(R.id.tabs)).peekWorkTabIfNecessary();
+ ((PersonalWorkSlidingTabStrip) findViewById(R.id.tabs)).highlightWorkTabIfNecessary();
}
}
diff --git a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
index 9fc4e2e..05cd655 100644
--- a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.allapps;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
@@ -30,7 +29,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.util.Themes;
/**
@@ -39,8 +37,6 @@
public class PersonalWorkSlidingTabStrip extends LinearLayout {
private static final int POSITION_PERSONAL = 0;
private static final int POSITION_WORK = 1;
- private static final int PEEK_DURATION = 1000;
- private static final float PEAK_OFFSET = 0.4f;
private static final String KEY_SHOWED_PEEK_WORK_TAB = "showed_peek_work_tab";
@@ -139,25 +135,22 @@
mIndicatorRight, getHeight(), mSelectedIndicatorPaint);
}
- public void peekWorkTabIfNecessary() {
+ public void highlightWorkTabIfNecessary() {
if (mSharedPreferences.getBoolean(KEY_SHOWED_PEEK_WORK_TAB, false)) {
return;
}
if (mIndicatorPosition != POSITION_PERSONAL) {
return;
}
- peekWorkTab();
+ highlightWorkTab();
mSharedPreferences.edit().putBoolean(KEY_SHOWED_PEEK_WORK_TAB, true).apply();
}
- private void peekWorkTab() {
- final boolean isRtl = Utilities.isRtl(getResources());
- ValueAnimator animator = ValueAnimator.ofFloat(0, isRtl ? 1 - PEAK_OFFSET : PEAK_OFFSET, 0);
- animator.setDuration(PEEK_DURATION);
- animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- animator.addUpdateListener(
- animation -> updateIndicatorPosition(mIndicatorPosition,
- (float) animation.getAnimatedValue()));
- animator.start();
+ private void highlightWorkTab() {
+ View v = getChildAt(POSITION_WORK);
+ v.post(() -> {
+ v.setPressed(true);
+ v.setPressed(false);
+ });
}
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 883c33d..00dd3aa 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -54,7 +54,6 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
-import com.android.launcher3.graphics.IconNormalizer;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.provider.ImportDataTask;
diff --git a/src/com/android/launcher3/model/ModelPreload.java b/src/com/android/launcher3/model/ModelPreload.java
new file mode 100644
index 0000000..6f33bed
--- /dev/null
+++ b/src/com/android/launcher3/model/ModelPreload.java
@@ -0,0 +1,70 @@
+/*
+ * 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.model;
+
+import android.content.Context;
+import android.support.annotation.WorkerThread;
+import android.util.Log;
+
+import com.android.launcher3.AllAppsList;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherModel.ModelUpdateTask;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Utility class to preload LauncherModel
+ */
+public class ModelPreload implements ModelUpdateTask {
+
+ private static final String TAG = "ModelPreload";
+
+ private LauncherAppState mApp;
+ private LauncherModel mModel;
+ private BgDataModel mBgDataModel;
+ private AllAppsList mAllAppsList;
+
+ @Override
+ public final void init(LauncherAppState app, LauncherModel model, BgDataModel dataModel,
+ AllAppsList allAppsList, Executor uiExecutor) {
+ mApp = app;
+ mModel = model;
+ mBgDataModel = dataModel;
+ mAllAppsList = allAppsList;
+ }
+
+ @Override
+ public final void run() {
+ if (!mModel.isModelLoaded()) {
+ Log.d(TAG, "Workspace not loaded, loading now");
+ mModel.startLoaderForResults(
+ new LoaderResults(mApp, mBgDataModel, mAllAppsList, 0, null));
+ }
+ Log.d(TAG, "Preload completed : " + mModel.isModelLoaded());
+ onComplete(mModel.isModelLoaded());
+ }
+
+ /**
+ * Called when the task is complete
+ */
+ @WorkerThread
+ public void onComplete(boolean isSuccess) { }
+
+ public void start(Context context) {
+ LauncherAppState.getInstance(context).getModel().enqueueModelUpdateTask(this);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/util/VerticalSwipeController.java b/src/com/android/launcher3/util/VerticalSwipeController.java
index 5d47cd2..29477e3 100644
--- a/src/com/android/launcher3/util/VerticalSwipeController.java
+++ b/src/com/android/launcher3/util/VerticalSwipeController.java
@@ -259,7 +259,7 @@
});
float nextFrameProgress = Utilities.boundToRange(
- progress + velocity * SINGLE_FRAME_MS / getShiftRange(), 0f, 1f);
+ progress + velocity * SINGLE_FRAME_MS * mProgressMultiplier, 0f, 1f);
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(nextFrameProgress, targetState == mToState ? 1f : 0f);