Merge "Use icon splash screen when starting activity from widget interaction" into sc-dev
diff --git a/go/quickstep/res/layout/overview_panel.xml b/go/quickstep/res/layout/overview_panel.xml
deleted file mode 100644
index 241b63d..0000000
--- a/go/quickstep/res/layout/overview_panel.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
- <com.android.quickstep.views.LauncherRecentsView
- android:id="@+id/overview_panel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:accessibilityPaneTitle="@string/accessibility_recent_apps"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:background="?attr/overviewBackgroundColor"
- android:visibility="invisible" />
-
- <com.android.quickstep.views.SplitPlaceholderView
- android:id="@+id/split_placeholder"
- android:layout_width="match_parent"
- android:layout_height="@dimen/split_placeholder_size"
- android:background="@android:color/darker_gray"
- android:visibility="gone" />
-
- <include
- android:id="@+id/overview_actions_view"
- layout="@layout/overview_actions_container" />
-
-</merge>
diff --git a/go/quickstep/res/values/attrs.xml b/go/quickstep/res/values/attrs.xml
index 3adf462..03eab50 100644
--- a/go/quickstep/res/values/attrs.xml
+++ b/go/quickstep/res/values/attrs.xml
@@ -16,7 +16,6 @@
-->
<resources>
<!-- Attributes used for Overview theming -->
- <attr name="overviewBackgroundColor" format="color" />
<attr name="overviewButtonTextColor" format="color" />
<attr name="overviewButtonIconColor" format="color" />
<attr name="overviewButtonBackgroundColor" format="color" />
diff --git a/go/quickstep/res/values/colors.xml b/go/quickstep/res/values/colors.xml
index f815f54..ae72ef6 100644
--- a/go/quickstep/res/values/colors.xml
+++ b/go/quickstep/res/values/colors.xml
@@ -16,10 +16,8 @@
-->
<resources>
<!-- Overview -->
- <color name="go_overview_background_color">#DADADA</color>
- <color name="go_overview_background_color_dark">#000000</color>
<color name="go_overview_text_color">#3C4043</color>
<color name="go_overview_text_color_dark">#F8F9FA</color>
<color name="go_overview_button_color">#70FFFFFF</color>
- <color name="go_overview_button_color_dark">#303030</color>
+ <color name="go_overview_button_color_dark">#474747</color>
</resources>
diff --git a/go/quickstep/res/values/styles.xml b/go/quickstep/res/values/styles.xml
index 59f7377..ffe8f46 100644
--- a/go/quickstep/res/values/styles.xml
+++ b/go/quickstep/res/values/styles.xml
@@ -17,14 +17,12 @@
<resources>
<!-- App themes -->
<style name="AppTheme" parent="@style/LauncherTheme">
- <item name="overviewBackgroundColor">@color/go_overview_background_color</item>
<item name="overviewButtonTextColor">@color/go_overview_text_color</item>
<item name="overviewButtonIconColor">@color/go_overview_text_color</item>
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color</item>
</style>
<style name="AppTheme.Dark" parent="@style/LauncherTheme.Dark">
- <item name="overviewBackgroundColor">@color/go_overview_background_color_dark</item>
<item name="overviewButtonTextColor">@color/go_overview_text_color_dark</item>
<item name="overviewButtonIconColor">@color/go_overview_text_color_dark</item>
<item name="overviewButtonBackgroundColor">@color/go_overview_button_color_dark</item>
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 3a6e9b5..b823c36 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -51,7 +51,8 @@
public static final String ACTIONS_URL = "niu_actions_app_url";
public static final String ACTIONS_APP_PACKAGE = "niu_actions_app_package";
public static final String ACTIONS_ERROR_CODE = "niu_actions_app_error_code";
- public static final int ERROR_PERMISSIONS = 1;
+ public static final int ERROR_PERMISSIONS_STRUCTURE = 1;
+ public static final int ERROR_PERMISSIONS_SCREENSHOT = 2;
private static final String TAG = "TaskOverlayFactoryGo";
private AssistContentRequester mContentRequester;
@@ -75,7 +76,8 @@
private String mNIUPackageName;
private String mTaskPackageName;
private String mWebUrl;
- private boolean mAssistPermissionsEnabled;
+ private boolean mAssistStructurePermitted;
+ private boolean mAssistScreenshotPermitted;
private AssistContentRequester mFactoryContentRequester;
private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
@@ -104,7 +106,7 @@
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
mTaskPackageName = task.key.getPackageName();
- if (!mAssistPermissionsEnabled) {
+ if (!mAssistStructurePermitted || !mAssistScreenshotPermitted) {
return;
}
@@ -131,10 +133,14 @@
private void sendNIUIntent(String actionType) {
Intent intent = createNIUIntent(actionType);
// Only add and send the image if the appropriate permissions are held
- if (mAssistPermissionsEnabled) {
+ if (mAssistStructurePermitted && mAssistScreenshotPermitted) {
mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent);
} else {
- intent.putExtra(ACTIONS_ERROR_CODE, ERROR_PERMISSIONS);
+ // If both permissions are disabled, the structure error code takes priority
+ // The user must enable that one before they can enable screenshots
+ int code = mAssistStructurePermitted ? ERROR_PERMISSIONS_SCREENSHOT
+ : ERROR_PERMISSIONS_STRUCTURE;
+ intent.putExtra(ACTIONS_ERROR_CODE, code);
try {
mApplicationContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
@@ -164,11 +170,10 @@
@VisibleForTesting
public void checkSettings() {
ContentResolver contentResolver = mApplicationContext.getContentResolver();
- boolean structureEnabled = Settings.Secure.getInt(contentResolver,
+ mAssistStructurePermitted = Settings.Secure.getInt(contentResolver,
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1) != 0;
- boolean screenshotEnabled = Settings.Secure.getInt(contentResolver,
+ mAssistScreenshotPermitted = Settings.Secure.getInt(contentResolver,
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1) != 0;
- mAssistPermissionsEnabled = structureEnabled && screenshotEnabled;
String assistantPackage =
Settings.Secure.getString(contentResolver, Settings.Secure.ASSISTANT);
diff --git a/quickstep/res/drawable/ic_all_set.xml b/quickstep/res/drawable/ic_all_set.xml
index a6852aa..656c596 100644
--- a/quickstep/res/drawable/ic_all_set.xml
+++ b/quickstep/res/drawable/ic_all_set.xml
@@ -15,10 +15,10 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="42dp"
- android:height="40dp"
+ android:height="42dp"
android:viewportWidth="42"
- android:viewportHeight="40">
+ android:viewportHeight="42">
<path
- android:pathData="M38,14H25.38L27.28,4.86L27.34,4.22C27.34,3.4 27,2.64 26.46,2.1L24.34,0C24.34,0 10.16,13.7 10,14H0V40H32C33.66,40 35.08,39 35.68,37.56L41.72,23.46C41.9,23 42,22.52 42,22V18C42,15.8 40.2,14 38,14ZM10,36H4V18H10V36ZM38,22L32,36H14V16L22.68,7.32L20,18H38V22Z"
+ android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"
android:fillColor="#FFFFFF"/>
</vector>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 33dc6cf..2498d12 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -430,7 +430,7 @@
public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
ActivityOptionsWrapper activityOptions =
mAppTransitionManager.hasControlRemoteAppTransitionPermission()
- ? mAppTransitionManager.getActivityLaunchOptions(this, v)
+ ? mAppTransitionManager.getActivityLaunchOptions(v)
: super.getActivityLaunchOptions(v, item);
if (mLastTouchUpTime > 0) {
ActivityOptionsCompat.setLauncherSourceInfo(
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
index 1090099..661053a 100644
--- a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -36,26 +36,48 @@
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import java.lang.ref.WeakReference;
+
+/**
+ * This class is needed to wrap any animation runner that is a part of the
+ * RemoteAnimationDefinition:
+ * - Launcher creates a new instance of the LauncherAppTransitionManagerImpl whenever it is
+ * created, which in turn registers a new definition
+ * - When the definition is registered, window manager retains a strong binder reference to the
+ * runner passed in
+ * - If the Launcher activity is recreated, the new definition registered will replace the old
+ * reference in the system's activity record, but until the system server is GC'd, the binder
+ * reference will still exist, which references the runner in the Launcher process, which
+ * references the (old) Launcher activity through this class
+ *
+ * Instead we make the runner provided to the definition static only holding a weak reference to
+ * the runner implementation. When this animation manager is destroyed, we remove the Launcher
+ * reference to the runner, leaving only the weak ref from the runner.
+ */
@TargetApi(Build.VERSION_CODES.P)
-public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
+public class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
+
+ private static final RemoteAnimationFactory DEFAULT_FACTORY =
+ (transit, appTargets, wallpaperTargets, nonAppTargets, result) ->
+ result.setAnimation(null, null);
private final Handler mHandler;
private final boolean mStartAtFrontOfQueue;
+ private final WeakReference<RemoteAnimationFactory> mFactory;
+
private AnimationResult mAnimationResult;
/**
* @param startAtFrontOfQueue If true, the animation start will be posted at the front of the
* queue to minimize latency.
*/
- public LauncherAnimationRunner(Handler handler, boolean startAtFrontOfQueue) {
+ public LauncherAnimationRunner(Handler handler, RemoteAnimationFactory factory,
+ boolean startAtFrontOfQueue) {
mHandler = handler;
+ mFactory = new WeakReference<>(factory);
mStartAtFrontOfQueue = startAtFrontOfQueue;
}
- public Handler getHandler() {
- return mHandler;
- }
-
// Called only in S+ platform
@BinderThread
public void onAnimationStart(
@@ -67,7 +89,7 @@
Runnable r = () -> {
finishExistingAnimation();
mAnimationResult = new AnimationResult(() -> mAnimationResult = null, runnable);
- onCreateAnimation(transit, appTargets, wallpaperTargets, nonAppTargets,
+ getFactory().onCreateAnimation(transit, appTargets, wallpaperTargets, nonAppTargets,
mAnimationResult);
};
if (mStartAtFrontOfQueue) {
@@ -92,17 +114,11 @@
onAnimationStart(appTargets, new RemoteAnimationTargetCompat[0], runnable);
}
- /**
- * Called on the UI thread when the animation targets are received. The implementation must
- * call {@link AnimationResult#setAnimation} with the target animation to be run.
- */
- @UiThread
- public abstract void onCreateAnimation(
- int transit,
- RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- RemoteAnimationTargetCompat[] nonAppTargets,
- AnimationResult result);
+
+ private RemoteAnimationFactory getFactory() {
+ RemoteAnimationFactory factory = mFactory.get();
+ return factory != null ? factory : DEFAULT_FACTORY;
+ }
@UiThread
private void finishExistingAnimation() {
@@ -118,7 +134,10 @@
@BinderThread
@Override
public void onAnimationCancelled() {
- postAsyncCallback(mHandler, this::finishExistingAnimation);
+ postAsyncCallback(mHandler, () -> {
+ finishExistingAnimation();
+ getFactory().onAnimationCancelled();
+ });
}
public static final class AnimationResult {
@@ -153,7 +172,6 @@
@UiThread
public void setAnimation(AnimatorSet animation, Context context) {
setAnimation(animation, context, null, true);
-
}
/**
@@ -198,4 +216,28 @@
}
}
}
+
+ /**
+ * Used with LauncherAnimationRunner as an interface for the runner to call back to the
+ * implementation.
+ */
+ @FunctionalInterface
+ public interface RemoteAnimationFactory {
+
+ /**
+ * Called on the UI thread when the animation targets are received. The implementation must
+ * call {@link AnimationResult#setAnimation} with the target animation to be run.
+ */
+ void onCreateAnimation(int transit,
+ RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets,
+ RemoteAnimationTargetCompat[] nonAppTargets,
+ LauncherAnimationRunner.AnimationResult result);
+
+ /**
+ * Called when the animation is cancelled. This can happen with or without
+ * the create being called.
+ */
+ default void onAnimationCancelled() { }
+ }
}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index dd248e4..3b3f0bd 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -79,6 +79,7 @@
import androidx.core.graphics.ColorUtils;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.icons.FastBitmapDrawable;
@@ -197,11 +198,11 @@
private RemoteAnimationProvider mRemoteAnimationProvider;
// Strong refs to runners which are cleared when the launcher activity is destroyed
- private WrappedAnimationRunnerImpl mWallpaperOpenRunner;
- private WrappedAnimationRunnerImpl mAppLaunchRunner;
- private WrappedAnimationRunnerImpl mKeyguardGoingAwayRunner;
+ private RemoteAnimationFactory mWallpaperOpenRunner;
+ private RemoteAnimationFactory mAppLaunchRunner;
+ private RemoteAnimationFactory mKeyguardGoingAwayRunner;
- private WrappedAnimationRunnerImpl mWallpaperOpenTransitionRunner;
+ private RemoteAnimationFactory mWallpaperOpenTransitionRunner;
private RemoteTransitionCompat mLauncherOpenTransition;
private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() {
@@ -257,11 +258,11 @@
* @return ActivityOptions with remote animations that controls how the window of the opening
* targets are displayed.
*/
- public ActivityOptionsWrapper getActivityLaunchOptions(Launcher launcher, View v) {
+ public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
RunnableList onEndCallback = new RunnableList();
- mAppLaunchRunner = new AppLaunchAnimationRunner(mHandler, v, onEndCallback);
- RemoteAnimationRunnerCompat runner = new WrappedLauncherAnimationRunner<>(
+ mAppLaunchRunner = new AppLaunchAnimationRunner(v, onEndCallback);
+ RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(
mHandler, mAppLaunchRunner, true /* startAtFrontOfQueue */);
// Note that this duration is a guess as we do not know if the animation will be a
@@ -1006,7 +1007,7 @@
definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
WindowManagerWrapper.ACTIVITY_TYPE_STANDARD,
new RemoteAnimationAdapterCompat(
- new WrappedLauncherAnimationRunner<>(mHandler, mWallpaperOpenRunner,
+ new LauncherAnimationRunner(mHandler, mWallpaperOpenRunner,
false /* startAtFrontOfQueue */),
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
@@ -1015,7 +1016,7 @@
definition.addRemoteAnimation(
WindowManagerWrapper.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
new RemoteAnimationAdapterCompat(
- new WrappedLauncherAnimationRunner<>(
+ new LauncherAnimationRunner(
mHandler, mKeyguardGoingAwayRunner,
true /* startAtFrontOfQueue */),
CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */));
@@ -1035,7 +1036,7 @@
if (hasControlRemoteAppTransitionPermission()) {
mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
mLauncherOpenTransition = RemoteAnimationAdapterCompat.buildRemoteTransition(
- new WrappedLauncherAnimationRunner<>(mHandler, mWallpaperOpenTransitionRunner,
+ new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
false /* startAtFrontOfQueue */));
mLauncherOpenTransition.addHomeOpenCheck();
SystemUiProxy.INSTANCE.getNoCreate().registerRemoteTransition(mLauncherOpenTransition);
@@ -1085,7 +1086,7 @@
* @return Runner that plays when user goes to Launcher
* ie. pressing home, swiping up from nav bar.
*/
- WrappedAnimationRunnerImpl createWallpaperOpenRunner(boolean fromUnlock) {
+ RemoteAnimationFactory createWallpaperOpenRunner(boolean fromUnlock) {
return new WallpaperOpenLauncherAnimationRunner(mHandler, fromUnlock);
}
@@ -1235,7 +1236,7 @@
/**
* Remote animation runner for animation from the app to Launcher, including recents.
*/
- protected class WallpaperOpenLauncherAnimationRunner implements WrappedAnimationRunnerImpl {
+ protected class WallpaperOpenLauncherAnimationRunner implements RemoteAnimationFactory {
private final Handler mHandler;
private final boolean mFromUnlock;
@@ -1323,17 +1324,12 @@
/**
* Remote animation runner for animation to launch an app.
*/
- private class AppLaunchAnimationRunner implements WrappedAnimationRunnerImpl {
+ private class AppLaunchAnimationRunner implements RemoteAnimationFactory {
- private static final String TRANSITION_LAUNCH_FROM_RECENTS = "transition:LaunchFromRecents";
- private static final String TRANSITION_LAUNCH_FROM_ICON = "transition:LaunchFromIcon";
-
- private final Handler mHandler;
private final View mV;
private final RunnableList mOnEndCallback;
- AppLaunchAnimationRunner(Handler handler, View v, RunnableList onEndCallback) {
- mHandler = handler;
+ AppLaunchAnimationRunner(View v, RunnableList onEndCallback) {
mV = v;
mOnEndCallback = onEndCallback;
}
@@ -1377,6 +1373,11 @@
result.setAnimation(anim, mLauncher, mOnEndCallback::executeAllAndDestroy,
skipFirstFrame);
}
+
+ @Override
+ public void onAnimationCancelled() {
+ mOnEndCallback.executeAllAndDestroy();
+ }
}
/**
diff --git a/quickstep/src/com/android/launcher3/WrappedAnimationRunnerImpl.java b/quickstep/src/com/android/launcher3/WrappedAnimationRunnerImpl.java
deleted file mode 100644
index 16727ec..0000000
--- a/quickstep/src/com/android/launcher3/WrappedAnimationRunnerImpl.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-
-/**
- * Used with WrappedLauncherAnimationRunner as an interface for the runner to call back to the
- * implementation.
- */
-public interface WrappedAnimationRunnerImpl {
-
- void onCreateAnimation(int transit,
- RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- RemoteAnimationTargetCompat[] nonAppTargets,
- LauncherAnimationRunner.AnimationResult result);
-}
diff --git a/quickstep/src/com/android/launcher3/WrappedLauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/WrappedLauncherAnimationRunner.java
deleted file mode 100644
index e319275..0000000
--- a/quickstep/src/com/android/launcher3/WrappedLauncherAnimationRunner.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.os.Handler;
-
-import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
-
-import java.lang.ref.WeakReference;
-
-/**
- * This class is needed to wrap any animation runner that is a part of the
- * RemoteAnimationDefinition:
- * - Launcher creates a new instance of the LauncherAppTransitionManagerImpl whenever it is
- * created, which in turn registers a new definition
- * - When the definition is registered, window manager retains a strong binder reference to the
- * runner passed in
- * - If the Launcher activity is recreated, the new definition registered will replace the old
- * reference in the system's activity record, but until the system server is GC'd, the binder
- * reference will still exist, which references the runner in the Launcher process, which
- * references the (old) Launcher activity through this class
- *
- * Instead we make the runner provided to the definition static only holding a weak reference to
- * the runner implementation. When this animation manager is destroyed, we remove the Launcher
- * reference to the runner, leaving only the weak ref from the runner.
- */
-public class WrappedLauncherAnimationRunner<R extends WrappedAnimationRunnerImpl>
- extends LauncherAnimationRunner {
- private WeakReference<R> mImpl;
-
- public WrappedLauncherAnimationRunner(
- Handler handler, R animationRunnerImpl, boolean startAtFrontOfQueue) {
- super(handler, startAtFrontOfQueue);
- mImpl = new WeakReference<>(animationRunnerImpl);
- }
-
- @Override
- public void onCreateAnimation(int transit,
- RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- RemoteAnimationTargetCompat[] nonAppTargets,
- AnimationResult result) {
- R animationRunnerImpl = mImpl.get();
- if (animationRunnerImpl != null) {
- animationRunnerImpl.onCreateAnimation(transit, appTargets, wallpaperTargets,
- nonAppTargets, result);
- }
- }
-}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 5b4e5f2..e6333d1 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -161,14 +161,14 @@
if (mSurface != surface) {
mSurface = surface;
if (surface != null) {
- dispatchTransactionSurface(mDepth);
+ dispatchTransactionSurface();
}
}
}
@Override
public void setState(LauncherState toState) {
- if (mSurface == null || mIgnoreStateChangesDuringMultiWindowAnimation) {
+ if (mIgnoreStateChangesDuringMultiWindowAnimation) {
return;
}
@@ -176,7 +176,7 @@
if (Float.compare(mDepth, toDepth) != 0) {
setDepth(toDepth);
} else if (toState == LauncherState.OVERVIEW) {
- dispatchTransactionSurface(mDepth);
+ dispatchTransactionSurface();
}
}
@@ -202,35 +202,30 @@
if (Float.compare(mDepth, depthF) == 0) {
return;
}
- if (dispatchTransactionSurface(depthF)) {
- mDepth = depthF;
- }
+ mDepth = depthF;
+ dispatchTransactionSurface();
}
- private boolean dispatchTransactionSurface(float depth) {
+ private void dispatchTransactionSurface() {
boolean supportsBlur = BlurUtils.supportsBlursOnWindows();
- if (supportsBlur && (mSurface == null || !mSurface.isValid())) {
- return false;
- }
ensureDependencies();
IBinder windowToken = mLauncher.getRootView().getWindowToken();
if (windowToken != null) {
- mWallpaperManager.setWallpaperZoomOut(windowToken, depth);
+ mWallpaperManager.setWallpaperZoomOut(windowToken, mDepth);
}
- if (supportsBlur) {
+ if (supportsBlur && (mSurface != null && mSurface.isValid())) {
// We cannot mark the window as opaque in overview because there will be an app window
// below the launcher layer, and we need to draw it -- without blurs.
boolean isOverview = mLauncher.isInState(LauncherState.OVERVIEW);
boolean opaque = mLauncher.getScrimView().isFullyOpaque() && !isOverview;
- int blur = opaque || isOverview ? 0 : (int) (depth * mMaxBlurRadius);
+ int blur = opaque || isOverview ? 0 : (int) (mDepth * mMaxBlurRadius);
new SurfaceControl.Transaction()
.setBackgroundBlurRadius(mSurface, blur)
.setOpaque(mSurface, opaque)
.apply();
}
- return true;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
index 5e9515d..c2c721a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepInteractionHandler.java
@@ -57,7 +57,7 @@
}
Pair<Intent, ActivityOptions> options = remoteResponse.getLaunchOptions(view);
ActivityOptionsWrapper activityOptions = mLauncher.getAppTransitionManager()
- .getActivityLaunchOptions(mLauncher, hostView);
+ .getActivityLaunchOptions(hostView);
if (Utilities.ATLEAST_S && !pendingIntent.isActivity()) {
// In the event this pending intent eventually launches an activity, i.e. a trampoline,
// use the Quickstep transition animation.
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index eb524a9..0e2fbbc 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -86,7 +86,7 @@
StateAnimationConfig config) {
RecentsView overview = mActivity.getOverviewPanel();
if (toState == NORMAL && fromState == OVERVIEW) {
- config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, DEACCEL);
+ config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR, 0, 0.25f));
config.setInterpolator(ANIM_SCRIM_FADE, LINEAR);
config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 3d66823..9d99f97 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -49,9 +49,8 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
+import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
import com.android.launcher3.R;
-import com.android.launcher3.WrappedAnimationRunnerImpl;
-import com.android.launcher3.WrappedLauncherAnimationRunner;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
@@ -109,7 +108,7 @@
private StateManager<RecentsState> mStateManager;
// Strong refs to runners which are cleared when the activity is destroyed
- private WrappedAnimationRunnerImpl mActivityLaunchAnimationRunner;
+ private RemoteAnimationFactory mActivityLaunchAnimationRunner;
/**
* Init drag layer and overview panel views.
@@ -206,19 +205,25 @@
final TaskView taskView = (TaskView) v;
RunnableList onEndCallback = new RunnableList();
- mActivityLaunchAnimationRunner = (int transit,
- RemoteAnimationTargetCompat[] appTargets,
+ mActivityLaunchAnimationRunner = new RemoteAnimationFactory() {
+ @Override
+ public void onCreateAnimation(int transit, RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets,
- RemoteAnimationTargetCompat[] nonAppTargets,
- AnimationResult result) -> {
- AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
- wallpaperTargets, nonAppTargets);
- anim.addListener(resetStateListener());
- result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy,
- true /* skipFirstFrame */);
+ RemoteAnimationTargetCompat[] nonAppTargets, AnimationResult result) {
+ AnimatorSet anim = composeRecentsLaunchAnimator(taskView, appTargets,
+ wallpaperTargets, nonAppTargets);
+ anim.addListener(resetStateListener());
+ result.setAnimation(anim, RecentsActivity.this, onEndCallback::executeAllAndDestroy,
+ true /* skipFirstFrame */);
+ }
+
+ @Override
+ public void onAnimationCancelled() {
+ onEndCallback.executeAllAndDestroy();
+ }
};
- final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner<>(
+ final LauncherAnimationRunner wrapper = new LauncherAnimationRunner(
mUiHandler, mActivityLaunchAnimationRunner, true /* startAtFrontOfQueue */);
RemoteAnimationAdapterCompat adapterCompat = new RemoteAnimationAdapterCompat(
wrapper, RECENTS_LAUNCH_DURATION,
@@ -362,34 +367,37 @@
}
private void startHomeInternal() {
- WrappedLauncherAnimationRunner runner = new WrappedLauncherAnimationRunner(
- getMainThreadHandler(), this::onCreateAnimationToHome, true);
+ LauncherAnimationRunner runner = new LauncherAnimationRunner(
+ getMainThreadHandler(), mAnimationToHomeFactory, true);
RemoteAnimationAdapterCompat adapterCompat =
new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0);
startActivity(createHomeIntent(),
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat).toBundle());
}
- private void onCreateAnimationToHome(
- int transit, RemoteAnimationTargetCompat[] appTargets,
- RemoteAnimationTargetCompat[] wallpaperTargets,
- RemoteAnimationTargetCompat[] nonAppTargets, AnimationResult result) {
- AnimatorPlaybackController controller = getStateManager()
- .createAnimationToNewWorkspace(RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
- controller.dispatchOnStart();
+ private final RemoteAnimationFactory mAnimationToHomeFactory =
+ new RemoteAnimationFactory() {
+ @Override
+ public void onCreateAnimation(int transit, RemoteAnimationTargetCompat[] appTargets,
+ RemoteAnimationTargetCompat[] wallpaperTargets,
+ RemoteAnimationTargetCompat[] nonAppTargets, AnimationResult result) {
+ AnimatorPlaybackController controller = getStateManager()
+ .createAnimationToNewWorkspace(RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
+ controller.dispatchOnStart();
- RemoteAnimationTargets targets = new RemoteAnimationTargets(
- appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
- for (RemoteAnimationTargetCompat app : targets.apps) {
- new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
+ RemoteAnimationTargets targets = new RemoteAnimationTargets(
+ appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
+ for (RemoteAnimationTargetCompat app : targets.apps) {
+ new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
+ }
+ AnimatorSet anim = new AnimatorSet();
+ anim.play(controller.getAnimationPlayer());
+ anim.setDuration(HOME_APPEAR_DURATION);
+ result.setAnimation(anim, RecentsActivity.this,
+ () -> getStateManager().goToState(RecentsState.HOME, false),
+ true /* skipFirstFrame */);
}
- AnimatorSet anim = new AnimatorSet();
- anim.play(controller.getAnimationPlayer());
- anim.setDuration(HOME_APPEAR_DURATION);
- result.setAnimation(anim, this,
- () -> getStateManager().goToState(RecentsState.HOME, false),
- true /* skipFirstFrame */);
- }
+ };
@Override
protected void collectStateHandlers(List<StateHandler> out) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index e52405b..c9b68df 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -813,7 +813,13 @@
}
private void reset() {
- mConsumer = mUncheckedConsumer = mResetGestureInputConsumer;
+ if (mResetGestureInputConsumer != null) {
+ mConsumer = mUncheckedConsumer = mResetGestureInputConsumer;
+ } else {
+ // mResetGestureInputConsumer isn't initialized until onUserUnlocked(), so reset to
+ // NO_OP until then (we never want these to be null).
+ mConsumer = mUncheckedConsumer = InputConsumer.NO_OP;
+ }
mGestureState = DEFAULT_STATE;
// By default, use batching of the input events, but check receiver before using in the rare
// case that the monitor was disposed before the swipe settled
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
index a3cd7df..510820a 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
@@ -26,6 +26,8 @@
import static com.android.launcher3.Utilities.squaredHypot;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -199,6 +201,14 @@
float progress = (float) valueAnimator.getAnimatedValue();
SystemUiProxy.INSTANCE.get(mContext).onAssistantProgress(progress);
});
+ // Ensure that we always send a zero at the end to clear the invocation state.
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ SystemUiProxy.INSTANCE.get(mContext).onAssistantProgress(0f);
+ }
+ });
animator.setInterpolator(Interpolators.DEACCEL_2);
animator.start();
}
diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
index 5c6da16..98dbd47 100644
--- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
+++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java
@@ -21,15 +21,14 @@
import android.os.Handler;
import com.android.launcher3.LauncherAnimationRunner;
-import com.android.launcher3.WrappedAnimationRunnerImpl;
-import com.android.launcher3.WrappedLauncherAnimationRunner;
+import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
public abstract class RemoteAnimationProvider {
- WrappedAnimationRunnerImpl mAnimationRunner;
+ RemoteAnimationFactory mAnimationRunner;
public abstract AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] appTargets,
RemoteAnimationTargetCompat[] wallpaperTargets);
@@ -37,7 +36,7 @@
ActivityOptions toActivityOptions(Handler handler, long duration, Context context) {
mAnimationRunner = (transit, appTargets, wallpaperTargets, nonApps, result) ->
result.setAnimation(createWindowAnimation(appTargets, wallpaperTargets), context);
- final LauncherAnimationRunner wrapper = new WrappedLauncherAnimationRunner(
+ final LauncherAnimationRunner wrapper = new LauncherAnimationRunner(
handler, mAnimationRunner, false /* startAtFrontOfQueue */);
return ActivityOptionsCompat.makeRemoteAnimation(
new RemoteAnimationAdapterCompat(wrapper, duration, 0));
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 3d33e57..a147b68 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -41,9 +41,8 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.LauncherAnimationRunner;
+import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
import com.android.launcher3.R;
-import com.android.launcher3.WrappedAnimationRunnerImpl;
-import com.android.launcher3.WrappedLauncherAnimationRunner;
import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskAnimationManager;
@@ -101,14 +100,14 @@
return;
}
// Assume initial mInitialTaskId is for top/left part of screen
- WrappedAnimationRunnerImpl initialSplitRunnerWrapped = new SplitLaunchAnimationRunner(
+ RemoteAnimationFactory initialSplitRunnerWrapped = new SplitLaunchAnimationRunner(
mInitialTaskView, 0);
- WrappedAnimationRunnerImpl secondarySplitRunnerWrapped = new SplitLaunchAnimationRunner(
+ RemoteAnimationFactory secondarySplitRunnerWrapped = new SplitLaunchAnimationRunner(
taskView, 1);
- RemoteAnimationRunnerCompat initialSplitRunner = new WrappedLauncherAnimationRunner(
+ RemoteAnimationRunnerCompat initialSplitRunner = new LauncherAnimationRunner(
new Handler(Looper.getMainLooper()), initialSplitRunnerWrapped,
true /* startAtFrontOfQueue */);
- RemoteAnimationRunnerCompat secondarySplitRunner = new WrappedLauncherAnimationRunner(
+ RemoteAnimationRunnerCompat secondarySplitRunner = new LauncherAnimationRunner(
new Handler(Looper.getMainLooper()), secondarySplitRunnerWrapped,
true /* startAtFrontOfQueue */);
ActivityOptions initialOptions = ActivityOptionsCompat.makeRemoteAnimation(
@@ -192,7 +191,7 @@
* LEGACY
* Remote animation runner for animation to launch an app.
*/
- private class SplitLaunchAnimationRunner implements WrappedAnimationRunnerImpl {
+ private class SplitLaunchAnimationRunner implements RemoteAnimationFactory {
private final TaskView mV;
private final int mTargetState;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index df7f8b5..8c3e5b5 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2245,7 +2245,7 @@
public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView,
boolean shouldRemoveTask, long duration) {
if (mPendingAnimation != null) {
- mPendingAnimation.createPlaybackController().dispatchOnCancel();
+ mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
}
PendingAnimation anim = new PendingAnimation(duration);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index b2a7b1b..ae429d9 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -554,7 +554,13 @@
mIsClickableAsLiveTile = false;
RecentsView recentsView = getRecentsView();
- RemoteAnimationTargets targets = recentsView.getLiveTileParams().getTargetSet();
+ final RemoteAnimationTargets targets = recentsView.getLiveTileParams().getTargetSet();
+ if (targets == null) {
+ // If the recents animation is cancelled somehow between the parent if block and
+ // here, try to launch the task as a non live tile task.
+ launcherNonLiveTileTask();
+ return;
+ }
AnimatorSet anim = new AnimatorSet();
TaskViewUtils.composeRecentsLaunchAnimator(
@@ -576,17 +582,21 @@
});
anim.start();
} else {
- if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
- // User tapped to select second split screen app
- getRecentsView().confirmSplitSelect(this);
- } else {
- launchTaskAnimated();
- }
+ launcherNonLiveTileTask();
}
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_TAP);
}
+ private void launcherNonLiveTileTask() {
+ if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
+ // User tapped to select second split screen app
+ getRecentsView().confirmSplitSelect(this);
+ } else {
+ launchTaskAnimated();
+ }
+ }
+
/**
* Starts the task associated with this view and animates the startup.
* @return CompletionStage to indicate the animation completion or null if the launch failed.
diff --git a/res/color-night-v31/all_apps_tabs_background.xml b/res/color-night-v31/all_apps_tabs_background.xml
deleted file mode 100644
index b396f33..0000000
--- a/res/color-night-v31/all_apps_tabs_background.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral2_100"/>
-</selector>
\ No newline at end of file
diff --git a/res/color-night/all_apps_tabs_background.xml b/res/color-night/all_apps_tabs_background.xml
deleted file mode 100644
index c0c1621..0000000
--- a/res/color-night/all_apps_tabs_background.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="#E2E2E2"/>
-</selector>
\ No newline at end of file
diff --git a/res/drawable/all_apps_tabs_background.xml b/res/drawable/all_apps_tabs_background.xml
index 4e95315..bf7ee8c 100644
--- a/res/drawable/all_apps_tabs_background.xml
+++ b/res/drawable/all_apps_tabs_background.xml
@@ -13,13 +13,27 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:enterFadeDuration="500">
<item
- android:top="@dimen/all_apps_tabs_vertical_padding"
- android:bottom="@dimen/all_apps_tabs_vertical_padding">
+ android:id="@+id/unselected"
+ android:state_selected="false">
+ <ripple android:color="@color/all_apps_tab_background_selected">
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/all_apps_header_pill_corner_radius" />
+ <solid android:color="@color/all_apps_tabs_background" />
+ </shape>
+ </item>
+ </ripple>
+ </item>
+
+ <item
+ android:id="@+id/selected"
+ android:state_selected="true">
<shape android:shape="rectangle">
- <solid android:color="@color/all_apps_tabs_background" />
<corners android:radius="@dimen/all_apps_header_pill_corner_radius" />
+ <solid android:color="@color/all_apps_tab_background_selected" />
</shape>
</item>
-</layer-list>
\ No newline at end of file
+</selector>
\ No newline at end of file
diff --git a/res/layout/all_apps_personal_work_tabs.xml b/res/layout/all_apps_personal_work_tabs.xml
index cfaa261..11143fb 100644
--- a/res/layout/all_apps_personal_work_tabs.xml
+++ b/res/layout/all_apps_personal_work_tabs.xml
@@ -14,12 +14,12 @@
~ limitations under the License.
-->
-<com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tabs"
- android:layout_width="@dimen/all_apps_header_pills_width"
+ android:layout_width="match_parent"
android:layout_height="@dimen/all_apps_header_pill_height"
android:layout_gravity="center_horizontal"
- android:background="@drawable/all_apps_tabs_background"
android:orientation="horizontal"
style="@style/TextHeadline">
@@ -27,19 +27,25 @@
android:id="@+id/tab_personal"
android:layout_width="0dp"
android:layout_height="match_parent"
+ android:layout_marginEnd="@dimen/all_apps_tabs_button_horizontal_padding"
+ android:layout_marginVertical="@dimen/all_apps_tabs_vertical_padding"
android:layout_weight="1"
- android:background="@drawable/personal_work_tabs_ripple"
+ android:background="@drawable/all_apps_tabs_background"
android:text="@string/all_apps_personal_tab"
android:textColor="@color/all_apps_tab_text"
- android:textSize="14sp" />
+ android:textSize="14sp"
+ style="?android:attr/borderlessButtonStyle" />
<Button
android:id="@+id/tab_work"
android:layout_width="0dp"
android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/all_apps_tabs_button_horizontal_padding"
+ android:layout_marginVertical="@dimen/all_apps_tabs_vertical_padding"
android:layout_weight="1"
- android:background="@drawable/personal_work_tabs_ripple"
+ android:background="@drawable/all_apps_tabs_background"
android:text="@string/all_apps_work_tab"
android:textColor="@color/all_apps_tab_text"
- android:textSize="14sp" />
+ android:textSize="14sp"
+ style="?android:attr/borderlessButtonStyle" />
</com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip>
\ No newline at end of file
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index dca3e79..1b4f3b9 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -33,6 +33,8 @@
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
+ android:fontFamily="sans-serif-medium"
+ android:textSize="20sp"
tools:text="No widgets available" />
<!-- Fast scroller popup -->
diff --git a/res/layout/widgets_full_sheet_search_and_recommendations.xml b/res/layout/widgets_full_sheet_search_and_recommendations.xml
index a89f85f..4a3e20d 100644
--- a/res/layout/widgets_full_sheet_search_and_recommendations.xml
+++ b/res/layout/widgets_full_sheet_search_and_recommendations.xml
@@ -53,7 +53,7 @@
android:id="@+id/recommended_widget_table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="16dp"
+ android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
android:layout_marginTop="8dp"
android:background="@drawable/widgets_recommendation_background"
android:paddingVertical="@dimen/recommended_widgets_table_vertical_padding"
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index 0bfa2b2..7f84050 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -19,8 +19,7 @@
android:id="@+id/widgets_list_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="16dp"
- android:layout_marginBottom="@dimen/widget_list_entry_bottom_margin"
+ android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
android:orientation="horizontal"
launcher:appIconSize="48dp">
diff --git a/res/layout/widgets_personal_work_tabs.xml b/res/layout/widgets_personal_work_tabs.xml
index 15275a6..532c422 100644
--- a/res/layout/widgets_personal_work_tabs.xml
+++ b/res/layout/widgets_personal_work_tabs.xml
@@ -20,28 +20,34 @@
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="@dimen/all_apps_header_pill_height"
- android:layout_marginHorizontal="32dp"
+ android:gravity="center_horizontal"
android:orientation="horizontal"
- android:background="@drawable/all_apps_tabs_background"
+ android:layout_marginHorizontal="@dimen/widget_tabs_horizontal_margin"
style="@style/TextHeadline">
<Button
android:id="@+id/tab_personal"
android:layout_width="0dp"
android:layout_height="match_parent"
+ android:layout_marginEnd="@dimen/widget_tabs_button_horizontal_padding"
+ android:layout_marginVertical="@dimen/widget_apps_tabs_vertical_padding"
android:layout_weight="1"
- android:background="@drawable/personal_work_tabs_ripple"
+ android:background="@drawable/all_apps_tabs_background"
android:text="@string/widgets_full_sheet_personal_tab"
android:textColor="@color/all_apps_tab_text"
- android:textSize="14sp" />
+ android:textSize="14sp"
+ style="?android:attr/borderlessButtonStyle" />
<Button
android:id="@+id/tab_work"
android:layout_width="0dp"
android:layout_height="match_parent"
+ android:layout_marginEnd="@dimen/widget_tabs_button_horizontal_padding"
+ android:layout_marginVertical="@dimen/widget_apps_tabs_vertical_padding"
android:layout_weight="1"
- android:background="@drawable/personal_work_tabs_ripple"
+ android:background="@drawable/all_apps_tabs_background"
android:text="@string/widgets_full_sheet_work_tab"
android:textColor="@color/all_apps_tab_text"
- android:textSize="14sp" />
+ android:textSize="14sp"
+ style="?android:attr/borderlessButtonStyle" />
</com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip>
\ No newline at end of file
diff --git a/res/layout/widgets_search_bar.xml b/res/layout/widgets_search_bar.xml
index 6a4bb4d..0b354e8 100644
--- a/res/layout/widgets_search_bar.xml
+++ b/res/layout/widgets_search_bar.xml
@@ -6,7 +6,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="24dp"
- android:layout_marginHorizontal="16dp"
+ android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
android:background="@drawable/bg_widgets_searchbox">
<com.android.launcher3.ExtendedEditText
diff --git a/res/layout/widgets_table_container.xml b/res/layout/widgets_table_container.xml
index 4f70a05..ab470d8 100644
--- a/res/layout/widgets_table_container.xml
+++ b/res/layout/widgets_table_container.xml
@@ -18,5 +18,4 @@
android:id="@+id/widgets_table"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginHorizontal="16dp"
- android:layout_marginBottom="@dimen/widget_list_entry_bottom_margin"/>
+ android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 251f04a..bc63c06 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -93,14 +93,14 @@
<dimen name="all_apps_background_canvas_width">700dp</dimen>
<dimen name="all_apps_background_canvas_height">475dp</dimen>
<dimen name="all_apps_header_pill_height">48dp</dimen>
- <dimen name="all_apps_header_pill_corner_radius">18dp</dimen>
- <dimen name="all_apps_header_pills_width">348dp</dimen>
+ <dimen name="all_apps_header_pill_corner_radius">12dp</dimen>
<dimen name="all_apps_header_tab_height">48dp</dimen>
<dimen name="all_apps_tabs_indicator_height">2dp</dimen>
<dimen name="all_apps_header_top_padding">36dp</dimen>
<dimen name="all_apps_header_bottom_padding">6dp</dimen>
<dimen name="all_apps_work_profile_tab_footer_top_padding">16dp</dimen>
<dimen name="all_apps_work_profile_tab_footer_bottom_padding">20dp</dimen>
+ <dimen name="all_apps_tabs_button_horizontal_padding">4dp</dimen>
<dimen name="all_apps_tabs_vertical_padding">6dp</dimen>
<dimen name="all_apps_divider_height">2dp</dimen>
<dimen name="all_apps_divider_width">128dp</dimen>
@@ -136,6 +136,11 @@
<dimen name="widget_cell_horizontal_padding">16dp</dimen>
<dimen name="widget_cell_font_size">14sp</dimen>
+ <dimen name="widget_tabs_button_horizontal_padding">4dp</dimen>
+ <dimen name="widget_tabs_horizontal_margin">32dp</dimen>
+ <dimen name="widget_apps_header_pill_height">48dp</dimen>
+ <dimen name="widget_apps_tabs_vertical_padding">6dp</dimen>
+
<dimen name="recommended_widgets_table_vertical_padding">8dp</dimen>
<!-- Bottom margin for the search and recommended widgets container without work profile -->
@@ -147,7 +152,8 @@
<dimen name="widget_list_content_corner_radius">4dp</dimen>
<dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
- <dimen name="widget_list_entry_bottom_margin">2dp</dimen>
+ <dimen name="widget_list_entry_spacing">2dp</dimen>
+ <dimen name="widget_list_horizontal_margin">16dp</dimen>
<dimen name="widget_preview_shadow_blur">0.5dp</dimen>
<dimen name="widget_preview_key_shadow_distance">1dp</dimen>
diff --git a/res/values/id.xml b/res/values/id.xml
index 1bd40ce..1709c59 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -16,6 +16,7 @@
-->
<resources>
<item type="id" name="apps_list_view_work" />
+ <item type="id" name="tag_widget_entry" />
<item type="id" name="view_type_widgets_list" />
<item type="id" name="view_type_widgets_header" />
<item type="id" name="view_type_widgets_search_header" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 60c0774..3dbd760 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -85,12 +85,12 @@
<!-- Spoken text for screen readers. This text lets a user know that the button is used to clear
the text that the user entered in the search box. [CHAR_LIMIT=none] -->
<string name="widgets_full_sheet_cancel_button_description">Clear text from search box</string>
- <!-- Text shown when there is no widgets shown in the popup view showing all available widgets
- installed on the device. [CHAR_LIMIT=none] -->
- <string name="no_widgets_available">No widgets available</string>
- <!-- Text shown when there are no matching widget search results for user's search query.
+ <!-- Text shown when there are no widgets or shortcuts that can be added to the device.
[CHAR_LIMIT=none] -->
- <string name="no_search_results">No search results</string>
+ <string name="no_widgets_available">Widgets and shortcuts aren\'t available</string>
+ <!-- Text shown when there are no matching widget or shortcut search results for user's search
+ query. [CHAR_LIMIT=none] -->
+ <string name="no_search_results">No widgets or shortcuts found</string>
<!-- Tab label. A user can tap this tab to access their personal widgets. [CHAR_LIMIT=25] -->
<string name="widgets_full_sheet_personal_tab">Personal</string>
<!-- Tab label. A user can tap this tab to access their work widgets. [CHAR_LIMIT=25] -->
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 7d8b82a..85ca280 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -278,12 +278,19 @@
}
}
- public void dispatchOnStart() {
+ public AnimatorPlaybackController dispatchOnStart() {
callListenerCommandRecursively(mAnim, AnimatorListener::onAnimationStart);
+ return this;
}
- public void dispatchOnCancel() {
+ public AnimatorPlaybackController dispatchOnCancel() {
callListenerCommandRecursively(mAnim, AnimatorListener::onAnimationCancel);
+ return this;
+ }
+
+ public AnimatorPlaybackController dispatchOnEnd() {
+ callListenerCommandRecursively(mAnim, AnimatorListener::onAnimationEnd);
+ return this;
}
public void dispatchSetInterpolator(TimeInterpolator interpolator) {
@@ -328,7 +335,7 @@
public void onAnimationSuccess(Animator animator) {
// We wait for the spring (if any) to finish running before completing the end callback.
if (!mDispatched) {
- callListenerCommandRecursively(mAnim, AnimatorListener::onAnimationEnd);
+ dispatchOnEnd();
if (mEndAction != null) {
mEndAction.run();
}
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 3abcc2b..7091d2b 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -168,6 +168,8 @@
cellY = info.cellY;
spanX = info.spanX;
spanY = info.spanY;
+ minSpanX = info.minSpanX;
+ minSpanY = info.minSpanY;
rank = info.rank;
screenId = info.screenId;
itemType = info.itemType;
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index dbd9c28..915e140 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -113,12 +113,6 @@
Utilities.getPrefs(getApplicationContext()).registerOnSharedPreferenceChangeListener(this);
}
- @Override
- protected void onStop() {
- super.onStop();
- finish();
- }
-
/**
* Obtains the preference fragment to instantiate in this activity.
*
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 13d6568..b34af97 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -209,7 +209,7 @@
// Cancel the current animation. This will reset mState to mCurrentStableState, so store it.
STATE_TYPE fromState = mState;
- mConfig.reset();
+ cancelAnimation();
if (!animated) {
mAtomicAnimationFactory.cancelAllStateElementAnimation();
@@ -303,7 +303,7 @@
public AnimatorPlaybackController createAnimationToNewWorkspace(STATE_TYPE state,
StateAnimationConfig config) {
config.userControlled = true;
- mConfig.reset();
+ cancelAnimation();
config.copyTo(mConfig);
mConfig.playbackController = createAnimationToNewWorkspaceInternal(state)
.createPlaybackController();
@@ -393,6 +393,11 @@
*/
public void cancelAnimation() {
mConfig.reset();
+ // It could happen that a new animation is set as a result of an endListener on the
+ // existing animation.
+ while (mConfig.currentAnimation != null || mConfig.playbackController != null) {
+ mConfig.reset();
+ }
}
public void setCurrentUserControlledAnimation(AnimatorPlaybackController controller) {
@@ -508,14 +513,19 @@
* Cancels the current animation and resets config variables.
*/
public void reset() {
+ AnimatorSet anim = currentAnimation;
+ AnimatorPlaybackController pc = playbackController;
+
DEFAULT.copyTo(this);
targetState = null;
+ currentAnimation = null;
+ playbackController = null;
+ changeId++;
- if (playbackController != null) {
- playbackController.getAnimationPlayer().cancel();
- playbackController.dispatchOnCancel();
- } else if (currentAnimation != null) {
- AnimatorSet anim = currentAnimation;
+ if (pc != null) {
+ pc.getAnimationPlayer().cancel();
+ pc.dispatchOnCancel().dispatchOnEnd();
+ } else if (anim != null) {
anim.setDuration(0);
if (!anim.isStarted()) {
// If the animation is not started the listeners do not get notified,
@@ -525,10 +535,6 @@
}
anim.cancel();
}
-
- currentAnimation = null;
- playbackController = null;
- changeId++;
}
@Override
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
index 6dc6971..fe83f3f 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHost.java
@@ -60,6 +60,10 @@
private static final int FLAG_ACTIVITY_RESUMED = 1 << 3;
private static final int FLAGS_SHOULD_LISTEN =
FLAG_STATE_IS_NORMAL | FLAG_ACTIVITY_STARTED | FLAG_ACTIVITY_RESUMED;
+ // TODO(b/191735836): Replace with ActivityOptions.KEY_SPLASH_SCREEN_STYLE when un-hidden
+ private static final String KEY_SPLASH_SCREEN_STYLE = "android.activity.splashScreenStyle";
+ // TODO(b/191735836): Replace with SplashScreen.SPLASH_SCREEN_STYLE_EMPTY when un-hidden
+ private static final int SPLASH_SCREEN_STYLE_EMPTY = 0;
public static final int APPWIDGET_HOST_ID = 1024;
@@ -329,7 +333,9 @@
if (view == null) return null;
Object tag = view.getTag();
if (!(tag instanceof ItemInfo)) return null;
- return activity.getActivityLaunchOptions(view, (ItemInfo) tag).toBundle();
+ Bundle bundle = activity.getActivityLaunchOptions(view, (ItemInfo) tag).toBundle();
+ bundle.putInt(KEY_SPLASH_SCREEN_STYLE, SPLASH_SCREEN_STYLE_EMPTY);
+ return bundle;
}
private void sendActionCancelled(final BaseActivity activity, final int requestCode) {
diff --git a/src/com/android/launcher3/widget/model/WidgetsListSearchHeaderEntry.java b/src/com/android/launcher3/widget/model/WidgetsListSearchHeaderEntry.java
index c0f89bc..055e4ec 100644
--- a/src/com/android/launcher3/widget/model/WidgetsListSearchHeaderEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetsListSearchHeaderEntry.java
@@ -60,7 +60,7 @@
WidgetsListSearchHeaderEntry otherEntry = (WidgetsListSearchHeaderEntry) obj;
return mWidgets.equals(otherEntry.mWidgets) && mPkgItem.equals(otherEntry.mPkgItem)
&& mTitleSectionName.equals(otherEntry.mTitleSectionName)
- && mIsWidgetListShown;
+ && mIsWidgetListShown == otherEntry.mIsWidgetListShown;
}
/** Returns a copy of this {@link WidgetsListSearchHeaderEntry} with the widget list shown. */
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index 5d9adf0..b668c90 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_APP_EXPANDED;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Process;
import android.util.Log;
import android.util.Size;
@@ -34,6 +35,7 @@
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
+import androidx.recyclerview.widget.RecyclerView.LayoutParams;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.launcher3.BaseActivity;
@@ -107,7 +109,8 @@
@Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
@Nullable private RecyclerView mRecyclerView;
@Nullable private PackageUserKey mPendingClickHeader;
- private int mShortcutPreviewPadding;
+ private final int mShortcutPreviewPadding;
+ private final int mSpacingBetweenEntries;
private final WidgetPreviewLoadedCallback mPreviewLoadedCallback =
ignored -> updateVisibleEntries();
@@ -141,11 +144,28 @@
mShortcutPreviewPadding =
2 * context.getResources()
.getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
+ mSpacingBetweenEntries =
+ context.getResources().getDimensionPixelSize(R.dimen.widget_list_entry_spacing);
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
mRecyclerView = recyclerView;
+
+ mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
+ @Override
+ public void getItemOffsets(
+ @NonNull Rect outRect,
+ @NonNull View view,
+ @NonNull RecyclerView parent,
+ @NonNull RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+ int position = ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition();
+ boolean isHeader =
+ view.getTag(R.id.tag_widget_entry) instanceof WidgetsListBaseEntry.Header;
+ outRect.top += position > 0 && isHeader ? mSpacingBetweenEntries : 0;
+ }
+ });
}
@Override
@@ -329,7 +349,9 @@
@Override
public void onBindViewHolder(ViewHolder holder, int pos) {
ViewHolderBinder viewHolderBinder = mViewHolderBinders.get(getItemViewType(pos));
+ WidgetsListBaseEntry entry = mVisibleEntries.get(pos);
viewHolderBinder.bindViewHolder(holder, mVisibleEntries.get(pos), pos);
+ holder.itemView.setTag(R.id.tag_widget_entry, entry);
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
index cdab964..ef2adbb 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListHeader.java
@@ -30,7 +30,6 @@
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
-import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
@@ -59,7 +58,6 @@
@Nullable private HandlerRunnable mIconLoadRequest;
@Nullable private Drawable mIconDrawable;
private final int mIconSize;
- private final int mBottomMarginSize;
private ImageView mAppIcon;
private TextView mTitle;
@@ -86,8 +84,6 @@
R.styleable.WidgetsListRowHeader, defStyleAttr, /* defStyleRes= */ 0);
mIconSize = a.getDimensionPixelSize(R.styleable.WidgetsListRowHeader_appIconSize,
grid.iconSizePx);
- mBottomMarginSize =
- getResources().getDimensionPixelSize(R.dimen.widget_list_entry_bottom_margin);
}
@Override
@@ -146,13 +142,6 @@
public void setExpanded(boolean isExpanded) {
this.mIsExpanded = isExpanded;
mExpandToggle.setChecked(isExpanded);
- if (getLayoutParams() instanceof RecyclerView.LayoutParams) {
- int bottomMargin = isExpanded ? 0 : mBottomMarginSize;
- RecyclerView.LayoutParams layoutParams =
- ((RecyclerView.LayoutParams) getLayoutParams());
- layoutParams.bottomMargin = bottomMargin;
- setLayoutParams(layoutParams);
- }
}
/** Sets the {@link WidgetsListDrawableState} and refreshes the background drawable. */
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
index 3ee8b33..7671841 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecyclerView.java
@@ -52,7 +52,7 @@
private HeaderViewDimensionsProvider mHeaderViewDimensionsProvider;
private int mLastVisibleWidgetContentTableHeight = 0;
private int mWidgetHeaderHeight = 0;
- private final int mCollapsedHeaderBottomMarginSize;
+ private final int mSpacingBetweenEntries;
@Nullable private OnContentChangeListener mOnContentChangeListener;
public WidgetsRecyclerView(Context context) {
@@ -72,9 +72,9 @@
ActivityContext activity = ActivityContext.lookupContext(getContext());
DeviceProfile grid = activity.getDeviceProfile();
- // The bottom margin used when the header is not expanded.
- mCollapsedHeaderBottomMarginSize =
- getResources().getDimensionPixelSize(R.dimen.widget_list_entry_bottom_margin);
+ // The spacing used between entries.
+ mSpacingBetweenEntries =
+ getResources().getDimensionPixelSize(R.dimen.widget_list_entry_spacing);
}
@Override
@@ -270,16 +270,16 @@
if (untilIndex > mAdapter.getItems().size()) {
untilIndex = mAdapter.getItems().size();
}
- int expandedHeaderPosition = mAdapter.getSelectedHeaderPosition().orElse(-1);
int totalItemsHeight = 0;
for (int i = 0; i < untilIndex; i++) {
WidgetsListBaseEntry entry = mAdapter.getItems().get(i);
if (entry instanceof WidgetsListHeaderEntry
|| entry instanceof WidgetsListSearchHeaderEntry) {
totalItemsHeight += mWidgetHeaderHeight;
- if (expandedHeaderPosition != i) {
- // If the header is collapsed, include the bottom margin it will use.
- totalItemsHeight += mCollapsedHeaderBottomMarginSize;
+ if (i > 0) {
+ // Each header contains the spacing between entries as top decoration, except
+ // the first one.
+ totalItemsHeight += mSpacingBetweenEntries;
}
} else if (entry instanceof WidgetsListContentEntry) {
totalItemsHeight += mLastVisibleWidgetContentTableHeight;
diff --git a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
index df5d465..11185fb 100644
--- a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
@@ -16,118 +16,43 @@
package com.android.launcher3.workprofile;
import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
import android.util.AttributeSet;
-import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.pageindicators.PageIndicator;
/**
* Supports two indicator colors, dedicated for personal and work tabs.
*/
public class PersonalWorkSlidingTabStrip extends LinearLayout implements PageIndicator {
- private final Paint mSelectedIndicatorPaint;
-
- private int mTabVerticalPadding;
- private final int mSelectedIndicatorRadius;
-
- private int mIndicatorLeft = -1;
- private int mIndicatorRight = -1;
- private float mScrollOffset;
- private int mSelectedPosition = 0;
-
private OnActivePageChangedListener mOnActivePageChangedListener;
private int mLastActivePage = 0;
- private boolean mIsRtl;
public PersonalWorkSlidingTabStrip(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
- setWillNotDraw(false);
-
- mTabVerticalPadding =
- getResources().getDimensionPixelSize(R.dimen.all_apps_tabs_vertical_padding);
-
- mSelectedIndicatorRadius = getResources().getDimensionPixelSize(
- R.dimen.all_apps_header_pill_corner_radius);
-
- mSelectedIndicatorPaint = new Paint();
- mSelectedIndicatorPaint.setColor(
- context.getColor(R.color.all_apps_tab_background_selected));
-
- mIsRtl = Utilities.isRtl(getResources());
}
/**
* Highlights tab with index pos
*/
public void updateTabTextColor(int pos) {
- mSelectedPosition = pos;
for (int i = 0; i < getChildCount(); i++) {
Button tab = (Button) getChildAt(i);
tab.setSelected(i == pos);
}
}
- private void updateIndicatorPosition(float scrollOffset) {
- mScrollOffset = scrollOffset;
- updateIndicatorPosition();
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- updateTabTextColor(mSelectedPosition);
- updateIndicatorPosition(mScrollOffset);
- }
-
- private void updateIndicatorPosition() {
- int left = -1, right = -1;
- final View leftTab = getLeftTab();
- if (leftTab != null) {
- left = (int) (leftTab.getLeft() + leftTab.getWidth() * mScrollOffset);
- right = left + leftTab.getWidth();
- }
- setIndicatorPosition(left, right);
- }
-
- private View getLeftTab() {
- return mIsRtl ? getChildAt(1) : getChildAt(0);
- }
-
- private void setIndicatorPosition(int left, int right) {
- if (left != mIndicatorLeft || right != mIndicatorRight) {
- mIndicatorLeft = left;
- mIndicatorRight = right;
- invalidate();
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- canvas.drawRoundRect(mIndicatorLeft, mTabVerticalPadding, mIndicatorRight,
- getHeight() - mTabVerticalPadding, mSelectedIndicatorRadius,
- mSelectedIndicatorRadius, mSelectedIndicatorPaint);
- }
-
@Override
public void setScroll(int currentScroll, int totalScroll) {
- float scrollOffset = ((float) currentScroll) / totalScroll;
- updateIndicatorPosition(scrollOffset);
}
@Override
public void setActiveMarker(int activePage) {
updateTabTextColor(activePage);
- updateIndicatorPosition(mIsRtl ? 1 - activePage : activePage);
if (mOnActivePageChangedListener != null && mLastActivePage != activePage) {
mOnActivePageChangedListener.onActivePageChanged(activePage);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index e32250e..1cb6b2d 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -25,6 +25,7 @@
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
+import androidx.test.uiautomator.StaleObjectException;
import androidx.test.uiautomator.UiObject2;
import com.android.launcher3.testing.TestProtocol;
@@ -61,7 +62,13 @@
private boolean hasClickableIcon(UiObject2 allAppsContainer, UiObject2 appListRecycler,
BySelector appIconSelector, int displayBottom) {
- final UiObject2 icon = appListRecycler.findObject(appIconSelector);
+ final UiObject2 icon;
+ try {
+ icon = appListRecycler.findObject(appIconSelector);
+ } catch (StaleObjectException e) {
+ mLauncher.fail("All apps recycler disappeared from screen");
+ return false;
+ }
if (icon == null) {
LauncherInstrumentation.log("hasClickableIcon: icon not visible");
return false;
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index 57fd08a..21099b4 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -75,4 +75,9 @@
protected void expectActivityStartEvents() {
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
}
+
+ @Override
+ protected String launchableType() {
+ return "app icon";
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
index a40919b..ac0db08 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
@@ -20,8 +20,6 @@
import com.android.launcher3.testing.TestProtocol;
-import java.util.regex.Pattern;
-
/**
* Menu item in an app icon menu.
*/
@@ -51,4 +49,9 @@
protected void expectActivityStartEvents() {
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
}
+
+ @Override
+ protected String launchableType() {
+ return "app icon menu item";
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index c4a566b..ec0a740 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -53,23 +53,29 @@
protected abstract void expectActivityStartEvents();
+ protected abstract String launchableType();
+
private Background launch(BySelector selector) {
- LauncherInstrumentation.log("Launchable.launch before click " +
- mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
- final String label = mObject.getText();
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "clicking " + launchableType())) {
+ LauncherInstrumentation.log("Launchable.launch before click "
+ + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
+ final String label = mObject.getText();
- mLauncher.executeAndWaitForEvent(
- () -> {
- mLauncher.clickLauncherObject(mObject);
- expectActivityStartEvents();
- },
- event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Launching an app didn't open a new window: " + label);
+ mLauncher.executeAndWaitForEvent(
+ () -> {
+ mLauncher.clickLauncherObject(mObject);
+ expectActivityStartEvents();
+ },
+ event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
+ () -> "Launching an app didn't open a new window: " + label);
- mLauncher.assertTrue(
- "App didn't start: " + label + " (" + selector + ")",
- TestHelpers.wait(Until.hasObject(selector), LauncherInstrumentation.WAIT_TIME_MS));
- return new Background(mLauncher);
+ mLauncher.assertTrue(
+ "App didn't start: " + label + " (" + selector + ")",
+ TestHelpers.wait(Until.hasObject(selector),
+ LauncherInstrumentation.WAIT_TIME_MS));
+ return new Background(mLauncher);
+ }
}
/**
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 96e8222..af36175 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -496,10 +496,10 @@
}
}
- private void fail(String message) {
+ void fail(String message) {
checkForAnomaly();
Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
- "http://go/tapl test failure:\nSummary: " + getContextDescription()
+ "http://go/tapl test failure:\nContext: " + getContextDescription()
+ " - visible state is " + getVisibleStateMessage()
+ ";\nDetails: " + message, true)));
}
@@ -1449,6 +1449,9 @@
Rect getVisibleBounds(UiObject2 object) {
try {
return object.getVisibleBounds();
+ } catch (StaleObjectException e) {
+ fail("Object " + object + " disappeared from screen");
+ return null;
} catch (Throwable t) {
fail(t.toString());
return null;
diff --git a/tests/tapl/com/android/launcher3/tapl/Widget.java b/tests/tapl/com/android/launcher3/tapl/Widget.java
index 53ef796..3520318 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widget.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widget.java
@@ -46,4 +46,9 @@
protected void addExpectedEventsForLongClick() {
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT);
}
+
+ @Override
+ protected String launchableType() {
+ return "widget";
+ }
}