Snap for 7487213 from dc01385cc2 to sc-v2-release
Change-Id: I54ed501e33a49c6d4b3fad9762f0b8a97144c8e1
This commit is contained in:
@@ -573,4 +573,15 @@
|
||||
column="42"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="NewApi"
|
||||
message="Call requires API level 31 (current min is 26): `android.appwidget.AppWidgetHostView#setColorResources`"
|
||||
errorLine1=" setColorResources(mWallpaperColorResources);"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="packages/apps/Launcher3/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java"
|
||||
line="528"
|
||||
column="17"/>
|
||||
</issue>
|
||||
|
||||
</issues>
|
||||
|
||||
@@ -26,6 +26,7 @@ message ExtendedContainers {
|
||||
|
||||
oneof Container{
|
||||
DeviceSearchResultContainer device_search_result_container = 1;
|
||||
CorrectedDeviceSearchResultContainer corrected_device_search_result_container = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,3 +34,9 @@ message ExtendedContainers {
|
||||
message DeviceSearchResultContainer{
|
||||
optional int32 query_length = 1;
|
||||
}
|
||||
|
||||
// Represents on-device search result container with results from spell-corrected query.
|
||||
message CorrectedDeviceSearchResultContainer{
|
||||
optional int32 query_length = 1;
|
||||
}
|
||||
|
||||
|
||||
+613
-792
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+613
-793
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -423,7 +423,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
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(
|
||||
|
||||
@@ -36,26 +36,48 @@ import androidx.annotation.UiThread;
|
||||
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 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
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 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
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 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
postAsyncCallback(mHandler, this::finishExistingAnimation);
|
||||
postAsyncCallback(mHandler, () -> {
|
||||
finishExistingAnimation();
|
||||
getFactory().onAnimationCancelled();
|
||||
});
|
||||
}
|
||||
|
||||
public static final class AnimationResult {
|
||||
@@ -153,7 +172,6 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
@UiThread
|
||||
public void setAnimation(AnimatorSet animation, Context context) {
|
||||
setAnimation(animation, context, null, true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,4 +216,28 @@ public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ import androidx.annotation.Nullable;
|
||||
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 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
|
||||
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 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
* @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 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
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 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
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 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
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);
|
||||
@@ -1093,7 +1094,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
* @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);
|
||||
}
|
||||
|
||||
@@ -1243,7 +1244,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
/**
|
||||
* 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;
|
||||
@@ -1331,17 +1332,12 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@@ -1385,6 +1381,11 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
result.setAnimation(anim, mLauncher, mOnEndCallback::executeAllAndDestroy,
|
||||
skipFirstFrame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
mOnEndCallback.executeAllAndDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,65 +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);
|
||||
} else {
|
||||
result.setAnimation(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.os.IBinder;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.CrossWindowBlurListeners;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.ViewRootImpl;
|
||||
@@ -41,6 +42,8 @@ import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.systemui.shared.system.BlurUtils;
|
||||
import com.android.systemui.shared.system.WallpaperManagerCompat;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Controls blur and wallpaper zoom, for the Launcher surface only.
|
||||
*/
|
||||
@@ -96,11 +99,17 @@ public class DepthController implements StateHandler<LauncherState>,
|
||||
}
|
||||
};
|
||||
|
||||
private final Consumer<Boolean> mCrossWindowBlurListener = (enabled) -> {
|
||||
mCrossWindowBlursEnabled = enabled;
|
||||
dispatchTransactionSurface();
|
||||
};
|
||||
|
||||
private final Launcher mLauncher;
|
||||
/**
|
||||
* Blur radius when completely zoomed out, in pixels.
|
||||
*/
|
||||
private int mMaxBlurRadius;
|
||||
private boolean mCrossWindowBlursEnabled;
|
||||
private WallpaperManagerCompat mWallpaperManager;
|
||||
private SurfaceControl mSurface;
|
||||
/**
|
||||
@@ -123,6 +132,7 @@ public class DepthController implements StateHandler<LauncherState>,
|
||||
mMaxBlurRadius = mLauncher.getResources().getInteger(R.integer.max_depth_blur_radius);
|
||||
mWallpaperManager = new WallpaperManagerCompat(mLauncher);
|
||||
}
|
||||
|
||||
if (mLauncher.getRootView() != null && mOnAttachListener == null) {
|
||||
mOnAttachListener = new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
@@ -132,13 +142,20 @@ public class DepthController implements StateHandler<LauncherState>,
|
||||
if (windowToken != null) {
|
||||
mWallpaperManager.setWallpaperZoomOut(windowToken, mDepth);
|
||||
}
|
||||
CrossWindowBlurListeners.getInstance().addListener(mLauncher.getMainExecutor(),
|
||||
mCrossWindowBlurListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
CrossWindowBlurListeners.getInstance().removeListener(mCrossWindowBlurListener);
|
||||
}
|
||||
};
|
||||
mLauncher.getRootView().addOnAttachStateChangeListener(mOnAttachListener);
|
||||
if (mLauncher.getRootView().isAttachedToWindow()) {
|
||||
CrossWindowBlurListeners.getInstance().addListener(mLauncher.getMainExecutor(),
|
||||
mCrossWindowBlurListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +237,8 @@ public class DepthController implements StateHandler<LauncherState>,
|
||||
boolean isOverview = mLauncher.isInState(LauncherState.OVERVIEW);
|
||||
boolean opaque = mLauncher.getScrimView().isFullyOpaque() && !isOverview;
|
||||
|
||||
int blur = opaque || isOverview ? 0 : (int) (mDepth * mMaxBlurRadius);
|
||||
int blur = opaque || isOverview || !mCrossWindowBlursEnabled
|
||||
? 0 : (int) (mDepth * mMaxBlurRadius);
|
||||
new SurfaceControl.Transaction()
|
||||
.setBackgroundBlurRadius(mSurface, blur)
|
||||
.setOpaque(mSurface, opaque)
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
import android.window.SplashScreen;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
@@ -56,7 +57,7 @@ class QuickstepInteractionHandler implements RemoteViews.InteractionHandler {
|
||||
}
|
||||
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.
|
||||
@@ -70,6 +71,7 @@ class QuickstepInteractionHandler implements RemoteViews.InteractionHandler {
|
||||
}
|
||||
}
|
||||
activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
|
||||
Object itemInfo = hostView.getTag();
|
||||
if (itemInfo instanceof ItemInfo) {
|
||||
mLauncher.addLaunchCookie((ItemInfo) itemInfo, activityOptions.options);
|
||||
|
||||
@@ -49,9 +49,8 @@ import com.android.launcher3.DeviceProfile;
|
||||
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 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
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 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
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,
|
||||
@@ -263,6 +268,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
// onActivityStart callback.
|
||||
mFallbackRecentsView.setContentAlpha(1);
|
||||
super.onStart();
|
||||
mFallbackRecentsView.updateLocusId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -271,6 +277,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
|
||||
// Workaround for b/78520668, explicitly trim memory once UI is hidden
|
||||
onTrimMemory(TRIM_MEMORY_UI_HIDDEN);
|
||||
mFallbackRecentsView.updateLocusId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -362,34 +369,37 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -29,12 +29,8 @@ public class BackGestureTutorialFragment extends TutorialFragment {
|
||||
@Override
|
||||
Integer getFeedbackVideoResId(boolean forDarkMode) {
|
||||
return mTutorialType == TutorialType.RIGHT_EDGE_BACK_NAVIGATION
|
||||
? (forDarkMode
|
||||
? R.drawable.gesture_tutorial_motion_back_right_dark_mode
|
||||
: R.drawable.gesture_tutorial_motion_back_right_light_mode)
|
||||
: (forDarkMode
|
||||
? R.drawable.gesture_tutorial_motion_back_left_dark_mode
|
||||
: R.drawable.gesture_tutorial_motion_back_left_light_mode);
|
||||
? R.drawable.gesture_tutorial_motion_back_right
|
||||
: R.drawable.gesture_tutorial_motion_back_left;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -151,6 +151,7 @@ public class StatsLogCompatManager extends StatsLogManager {
|
||||
private Optional<ToState> mToState = Optional.empty();
|
||||
private Optional<String> mEditText = Optional.empty();
|
||||
private SliceItem mSliceItem;
|
||||
private LauncherAtom.Slice mSlice;
|
||||
|
||||
StatsCompatLogger(Context context) {
|
||||
mContext = context;
|
||||
@@ -193,7 +194,7 @@ public class StatsLogCompatManager extends StatsLogManager {
|
||||
@Override
|
||||
public StatsLogger withContainerInfo(ContainerInfo containerInfo) {
|
||||
checkState(mItemInfo == DEFAULT_ITEM_INFO,
|
||||
"ItemInfo and ContainerInfo are mutual exclusive; cannot log both.");
|
||||
"ItemInfo and ContainerInfo are mutual exclusive; cannot log both.");
|
||||
this.mContainerInfo = Optional.of(containerInfo);
|
||||
return this;
|
||||
}
|
||||
@@ -218,9 +219,21 @@ public class StatsLogCompatManager extends StatsLogManager {
|
||||
|
||||
@Override
|
||||
public StatsLogger withSliceItem(@NonNull SliceItem sliceItem) {
|
||||
checkState(mItemInfo == DEFAULT_ITEM_INFO && mSlice == null,
|
||||
"ItemInfo, Slice and SliceItem are mutual exclusive; cannot set more than one"
|
||||
+ " of them.");
|
||||
this.mSliceItem = checkNotNull(sliceItem, "expected valid sliceItem but received null");
|
||||
checkState(mItemInfo == DEFAULT_ITEM_INFO,
|
||||
"ItemInfo and SliceItem are mutual exclusive; cannot log both.");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatsLogger withSlice(LauncherAtom.Slice slice) {
|
||||
checkState(mItemInfo == DEFAULT_ITEM_INFO && mSliceItem == null,
|
||||
"ItemInfo, Slice and SliceItem are mutual exclusive; cannot set more than one"
|
||||
+ " of them.");
|
||||
checkNotNull(slice, "expected valid slice but received null");
|
||||
checkNotNull(slice.getUri(), "expected valid slice uri but received null");
|
||||
this.mSlice = slice;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -231,13 +244,16 @@ public class StatsLogCompatManager extends StatsLogManager {
|
||||
}
|
||||
LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
|
||||
|
||||
if (mSliceItem != null) {
|
||||
if (mSlice == null && mSliceItem != null) {
|
||||
mSlice = LauncherAtom.Slice.newBuilder().setUri(
|
||||
mSliceItem.getSlice().getUri().toString()).build();
|
||||
}
|
||||
|
||||
if (mSlice != null) {
|
||||
Executors.MODEL_EXECUTOR.execute(
|
||||
() -> {
|
||||
LauncherAtom.ItemInfo.Builder itemInfoBuilder =
|
||||
LauncherAtom.ItemInfo.newBuilder().setSlice(
|
||||
LauncherAtom.Slice.newBuilder().setUri(
|
||||
mSliceItem.getSlice().getUri().toString()));
|
||||
LauncherAtom.ItemInfo.newBuilder().setSlice(mSlice);
|
||||
mContainerInfo.ifPresent(itemInfoBuilder::setContainerInfo);
|
||||
write(event, applyOverwrites(itemInfoBuilder.build()));
|
||||
});
|
||||
|
||||
@@ -21,15 +21,14 @@ import android.content.Context;
|
||||
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 @@ public abstract class RemoteAnimationProvider {
|
||||
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));
|
||||
|
||||
@@ -41,9 +41,8 @@ import com.android.launcher3.BaseQuickstepLauncher;
|
||||
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 @@ public class SplitSelectStateController {
|
||||
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 @@ public class SplitSelectStateController {
|
||||
* 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;
|
||||
|
||||
@@ -62,6 +62,7 @@ import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.LocusId;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.BlendMode;
|
||||
import android.graphics.Canvas;
|
||||
@@ -74,6 +75,7 @@ import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
@@ -883,7 +885,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
finishRecentsAnimation(true /* toRecents */, null);
|
||||
finishRecentsAnimation(false /* toRecents */, null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -952,6 +954,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
cancelSplitSelect(false);
|
||||
}
|
||||
}
|
||||
updateLocusId();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2421,12 +2424,12 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
if (success) {
|
||||
if (shouldRemoveTask) {
|
||||
if (dismissedTaskView.getTask() != null) {
|
||||
finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
|
||||
() -> {
|
||||
UI_HELPER_EXECUTOR.getHandler().postDelayed(() ->
|
||||
ActivityManagerWrapper.getInstance().removeTask(
|
||||
dismissedTaskId), REMOVE_TASK_WAIT_FOR_APP_STOP_MS);
|
||||
});
|
||||
if (LIVE_TILE.get() && dismissedTaskView.isRunningTask()) {
|
||||
finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
|
||||
() -> removeTaskInternal(dismissedTaskId));
|
||||
} else {
|
||||
removeTaskInternal(dismissedTaskId);
|
||||
}
|
||||
mActivity.getStatsLogManager().logger()
|
||||
.withItemInfo(dismissedTaskView.getItemInfo())
|
||||
.log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
|
||||
@@ -2472,6 +2475,12 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
return anim;
|
||||
}
|
||||
|
||||
private void removeTaskInternal(int dismissedTaskId) {
|
||||
UI_HELPER_EXECUTOR.getHandler().postDelayed(
|
||||
() -> ActivityManagerWrapper.getInstance().removeTask(dismissedTaskId),
|
||||
REMOVE_TASK_WAIT_FOR_APP_STOP_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if one of the task thumbnails would intersect/overlap with the
|
||||
* {@link #mSplitPlaceholderView}
|
||||
@@ -3923,4 +3932,19 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
public RecentsAnimationController getRecentsAnimationController() {
|
||||
return mRecentsAnimationController;
|
||||
}
|
||||
|
||||
/** Update the current activity locus id to show the enabled state of Overview */
|
||||
public void updateLocusId() {
|
||||
String locusId = "Overview";
|
||||
|
||||
if (mOverviewStateEnabled && mActivity.isStarted()) {
|
||||
locusId += "|ENABLED";
|
||||
} else {
|
||||
locusId += "|DISABLED";
|
||||
}
|
||||
|
||||
final LocusId id = new LocusId(locusId);
|
||||
// Set locus context is a binder call, don't want it to happen during a transition
|
||||
UI_HELPER_EXECUTOR.post(() -> mActivity.setLocusContext(id, Bundle.EMPTY));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,7 +545,13 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
|
||||
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(
|
||||
@@ -567,17 +573,21 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
});
|
||||
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.
|
||||
|
||||
@@ -107,7 +107,7 @@ public class FallbackRecentsTest {
|
||||
|
||||
mOrderSensitiveRules = RuleChain
|
||||
.outerRule(new NavigationModeSwitchRule(mLauncher))
|
||||
.around(new FailureWatcher(mDevice));
|
||||
.around(new FailureWatcher(mDevice, mLauncher));
|
||||
|
||||
mOtherLauncherActivity = context.getPackageManager().queryIntentActivities(
|
||||
getHomeIntentInPackage(context),
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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_50"
|
||||
android:lStar="30" />
|
||||
</selector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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="?attr/popupColorPrimary"
|
||||
android:lStar="20" />
|
||||
</selector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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="?attr/popupColorPrimary"
|
||||
android:lStar="15" />
|
||||
</selector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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="?attr/popupColorPrimary"
|
||||
android:lStar="10" />
|
||||
</selector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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_neutral1_50"
|
||||
android:lStar="98" />
|
||||
</selector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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="?attr/popupColorPrimary"
|
||||
android:lStar="98" />
|
||||
</selector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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="?attr/popupColorPrimary"
|
||||
android:lStar="95" />
|
||||
</selector>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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="?attr/popupColorPrimary"
|
||||
android:lStar="90" />
|
||||
</selector>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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="?attr/popupColorPrimary" />
|
||||
</selector>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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="?attr/popupColorPrimary" />
|
||||
</selector>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?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="?attr/popupColorPrimary" />
|
||||
</selector>
|
||||
@@ -18,14 +18,18 @@
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="@dimen/work_fab_radius" />
|
||||
<solid android:color="?android:attr/colorControlHighlight" />
|
||||
<padding android:left="@dimen/work_fab_radius" android:right="@dimen/work_fab_radius" />
|
||||
<padding
|
||||
android:left="@dimen/work_profile_footer_padding"
|
||||
android:right="@dimen/work_profile_footer_padding" />
|
||||
</shape>
|
||||
</item>
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="@dimen/work_fab_radius" />
|
||||
<solid android:color="@color/all_apps_tab_background_selected" />
|
||||
<padding android:left="@dimen/work_fab_radius" android:right="@dimen/work_fab_radius" />
|
||||
<padding
|
||||
android:left="@dimen/work_profile_footer_padding"
|
||||
android:right="@dimen/work_profile_footer_padding" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="@dimen/rounded_button_height"
|
||||
android:id="@+id/action_btn"
|
||||
android:textColor="?attr/workProfileOverlayTextColor"
|
||||
android:text="@string/work_profile_edu_accept"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/work_edu_card_margin"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center">
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<TextView
|
||||
style="@style/PrimaryHeadline"
|
||||
@@ -25,8 +25,7 @@
|
||||
android:id="@+id/work_apps_paused_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:text="@string/work_apps_paused_title"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp" />
|
||||
@@ -38,12 +37,13 @@
|
||||
android:textColor="?attr/workProfileOverlayTextColor"
|
||||
android:text="@string/work_apps_paused_body"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="@dimen/rounded_button_height"
|
||||
android:id="@+id/enable_work_apps"
|
||||
android:textColor="?attr/workProfileOverlayTextColor"
|
||||
android:text="@string/work_apps_enable_btn_text"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<com.android.launcher3.allapps.WorkModeSwitch xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/TextHeadline"
|
||||
android:id="@+id/work_mode_toggle"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
@@ -22,6 +23,7 @@
|
||||
android:includeFontPadding="false"
|
||||
android:drawableTint="@color/all_apps_tab_text"
|
||||
android:textColor="@color/all_apps_tab_text"
|
||||
android:textSize="14sp"
|
||||
android:background="@drawable/work_apps_toggle_background"
|
||||
android:drawablePadding="16dp"
|
||||
android:drawableStart="@drawable/ic_corp_off"
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowShowWallpaper">true</item>
|
||||
<item name="folderTextColor">?attr/workspaceTextColor</item>
|
||||
<item name="isFolderDarkText">?attr/isWorkspaceDarkText</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
<item name="android:enforceStatusBarContrast">false</item>
|
||||
<item name="android:enforceNavigationBarContrast">false</item>
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowShowWallpaper">true</item>
|
||||
<item name="folderTextColor">?attr/workspaceTextColor</item>
|
||||
<item name="isFolderDarkText">?attr/isWorkspaceDarkText</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">always</item>
|
||||
<item name="android:enforceStatusBarContrast">false</item>
|
||||
<item name="android:enforceNavigationBarContrast">false</item>
|
||||
|
||||
@@ -39,9 +39,7 @@
|
||||
<color name="text_color_tertiary_dark">@android:color/system_neutral2_400</color>
|
||||
|
||||
<color name="wallpaper_popup_scrim">@android:color/system_neutral1_900</color>
|
||||
<color name="folder_background_light" android:lstar="98">@android:color/system_neutral1_50</color>
|
||||
<color name="folder_background_dark" android:lstar="30">@android:color/system_neutral2_800</color>
|
||||
|
||||
|
||||
<color name="folder_dot_color">@android:color/system_accent2_50</color>
|
||||
|
||||
|
||||
|
||||
@@ -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] -->
|
||||
@@ -140,8 +140,8 @@
|
||||
<string name="long_accessible_way_to_add_shortcut">Double-tap & hold to move a shortcut or use custom actions.</string>
|
||||
|
||||
<skip />
|
||||
<!-- Error message when user has filled a home screen -->
|
||||
<string name="out_of_space">No more room on this Home screen.</string>
|
||||
<!-- Error message when a user can't add more apps, widgets, or shortcuts to a Home screen. -->
|
||||
<string name="out_of_space">No room on this Home screen</string>
|
||||
<!-- Error message when user has filled the hotseat -->
|
||||
<string name="hotseat_out_of_space">No more room in the Favorites tray</string>
|
||||
|
||||
@@ -394,7 +394,7 @@
|
||||
<string name="work_profile_edu_accept">Got it</string>
|
||||
|
||||
<!--- heading shown when user opens work apps tab while work apps are paused -->
|
||||
<string name="work_apps_paused_title">Work apps are off</string>
|
||||
<string name="work_apps_paused_title">Work apps are paused</string>
|
||||
<!--- body shown when user opens work apps tab while work apps are paused -->
|
||||
<string name="work_apps_paused_body">Your work apps can’t send you notifications, use your battery, or access your location</string>
|
||||
<!-- content description for paused work apps list -->
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowShowWallpaper">true</item>
|
||||
<item name="folderTextColor">?attr/workspaceTextColor</item>
|
||||
<item name="isFolderDarkText">?attr/isWorkspaceDarkText</item>
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme" parent="@style/BaseLauncherTheme">
|
||||
@@ -72,10 +70,6 @@
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme.DarkMainColor" parent="@style/LauncherTheme">
|
||||
<item name="folderFillColor">@color/folder_background_dark</item>
|
||||
<item name="folderTextColor">@color/workspace_text_color_light</item>
|
||||
<item name="isFolderDarkText">false</item>
|
||||
<item name="folderHintColor">@color/folder_hint_text_color_light</item>
|
||||
<item name="disabledIconAlpha">.254</item>
|
||||
|
||||
</style>
|
||||
@@ -87,12 +81,6 @@
|
||||
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
|
||||
<item name="isWorkspaceDarkText">true</item>
|
||||
<item name="workspaceStatusBarScrim">@null</item>
|
||||
<item name="folderDotColor">@color/folder_dot_color</item>
|
||||
<item name="folderFillColor">@color/folder_background_light</item>
|
||||
<item name="folderIconBorderColor">#FF80868B</item>
|
||||
<item name="folderTextColor">@color/workspace_text_color_dark</item>
|
||||
<item name="isFolderDarkText">true</item>
|
||||
<item name="folderHintColor">@color/folder_hint_text_color_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme.Dark" parent="@style/LauncherTheme">
|
||||
@@ -125,25 +113,17 @@
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme.Dark.DarkMainColor" parent="@style/LauncherTheme.Dark">
|
||||
<item name="folderFillColor">@color/folder_background_dark</item>
|
||||
<item name="folderTextColor">@color/workspace_text_color_light</item>
|
||||
<item name="isFolderDarkText">false</item>
|
||||
<item name="folderHintColor">@color/folder_hint_text_color_light</item>
|
||||
<item name="disabledIconAlpha">.54</item>
|
||||
</style>
|
||||
|
||||
<style name="LauncherTheme.Dark.DarkText" parent="@style/LauncherTheme.Dark">
|
||||
<item name="android:colorControlHighlight">#19212121</item>
|
||||
<item name="folderFillColor">@color/folder_background_light</item>
|
||||
<item name="workspaceTextColor">@color/workspace_text_color_dark</item>
|
||||
<item name="workspaceShadowColor">@android:color/transparent</item>
|
||||
<item name="workspaceAmbientShadowColor">@android:color/transparent</item>
|
||||
<item name="workspaceKeyShadowColor">@android:color/transparent</item>
|
||||
<item name="isWorkspaceDarkText">true</item>
|
||||
<item name="workspaceStatusBarScrim">@null</item>
|
||||
<item name="folderTextColor">@color/workspace_text_color_dark</item>
|
||||
<item name="isFolderDarkText">true</item>
|
||||
<item name="folderHintColor">@color/folder_hint_text_color_dark</item>
|
||||
</style>
|
||||
|
||||
<!-- A derivative project can extend these themes to customize the application theme without
|
||||
|
||||
+24
@@ -122,6 +122,8 @@ public final class LauncherAppWidgetProviderInfoTest {
|
||||
@Test
|
||||
public void initSpans_minResizeWidthSmallerThanCellWidth_shouldInitializeMinSpansToOne() {
|
||||
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
|
||||
info.minWidth = 100;
|
||||
info.minHeight = 100;
|
||||
info.minResizeWidth = 20;
|
||||
info.minResizeHeight = 20;
|
||||
InvariantDeviceProfile idp = createIDP();
|
||||
@@ -135,6 +137,8 @@ public final class LauncherAppWidgetProviderInfoTest {
|
||||
@Test
|
||||
public void initSpans_minResizeWidthLargerThanCellWidth_shouldInitializeMinSpans() {
|
||||
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
|
||||
info.minWidth = 100;
|
||||
info.minHeight = 100;
|
||||
info.minResizeWidth = 80;
|
||||
info.minResizeHeight = 80;
|
||||
InvariantDeviceProfile idp = createIDP();
|
||||
@@ -157,6 +161,8 @@ public final class LauncherAppWidgetProviderInfoTest {
|
||||
Mockito.when(dp.shouldInsetWidgets()).thenReturn(true);
|
||||
|
||||
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
|
||||
info.minWidth = CELL_SIZE * 3;
|
||||
info.minHeight = CELL_SIZE * 3;
|
||||
info.minResizeWidth = CELL_SIZE * 2 + maxPadding;
|
||||
info.minResizeHeight = CELL_SIZE * 2 + maxPadding;
|
||||
|
||||
@@ -177,6 +183,8 @@ public final class LauncherAppWidgetProviderInfoTest {
|
||||
dp.cellLayoutBorderSpacingPx = maxPadding - 1;
|
||||
Mockito.when(dp.shouldInsetWidgets()).thenReturn(false);
|
||||
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
|
||||
info.minWidth = CELL_SIZE * 3;
|
||||
info.minHeight = CELL_SIZE * 3;
|
||||
info.minResizeWidth = CELL_SIZE * 2 + maxPadding;
|
||||
info.minResizeHeight = CELL_SIZE * 2 + maxPadding;
|
||||
|
||||
@@ -186,6 +194,22 @@ public final class LauncherAppWidgetProviderInfoTest {
|
||||
assertThat(info.minSpanY).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void
|
||||
initSpans_minResizeWidthHeightLargerThanMinWidth_shouldUseMinWidthHeightAsMinSpans() {
|
||||
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
|
||||
info.minWidth = 20;
|
||||
info.minHeight = 20;
|
||||
info.minResizeWidth = 80;
|
||||
info.minResizeHeight = 80;
|
||||
InvariantDeviceProfile idp = createIDP();
|
||||
|
||||
info.initSpans(mContext, idp);
|
||||
|
||||
assertThat(info.minSpanX).isEqualTo(1);
|
||||
assertThat(info.minSpanY).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isMinSizeFulfilled_minWidthAndHeightWithinGridSize_shouldReturnTrue() {
|
||||
LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
|
||||
|
||||
@@ -684,9 +684,6 @@ public class CellLayout extends ViewGroup {
|
||||
if (child instanceof BubbleTextView) {
|
||||
BubbleTextView bubbleChild = (BubbleTextView) child;
|
||||
bubbleChild.setTextVisibility(mContainerType != HOTSEAT);
|
||||
if (mActivity.getDeviceProfile().isScalableGrid) {
|
||||
bubbleChild.setCenterVertically(mContainerType != HOTSEAT);
|
||||
}
|
||||
}
|
||||
|
||||
child.setScaleX(mChildScale);
|
||||
|
||||
@@ -152,10 +152,11 @@ public class DeviceProfile {
|
||||
// Hotseat
|
||||
public final int numShownHotseatIcons;
|
||||
public int hotseatCellHeightPx;
|
||||
private final int hotseatExtraVerticalSize;
|
||||
// In portrait: size = height, in landscape: size = width
|
||||
public int hotseatBarSizePx;
|
||||
public final int hotseatBarTopPaddingPx;
|
||||
public int hotseatBarBottomPaddingPx;
|
||||
public final int hotseatBarBottomPaddingPx;
|
||||
// Start is the side next to the nav bar, end is the side next to the workspace
|
||||
public final int hotseatBarSidePaddingStartPx;
|
||||
public final int hotseatBarSidePaddingEndPx;
|
||||
@@ -331,13 +332,9 @@ public class DeviceProfile {
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
|
||||
// Add a bit of space between nav bar and hotseat in vertical bar layout.
|
||||
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
|
||||
int hotseatExtraVerticalSize =
|
||||
hotseatExtraVerticalSize =
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
|
||||
hotseatBarSizePx = pxFromDp(inv.iconSize, mMetrics, 1f)
|
||||
+ (isVerticalBarLayout()
|
||||
? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
|
||||
: (hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx
|
||||
+ (isScalableGrid ? 0 : hotseatExtraVerticalSize)));
|
||||
updateHotseatIconSize(pxFromDp(inv.iconSize, mMetrics, 1f));
|
||||
|
||||
overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin);
|
||||
overviewTaskIconSizePx =
|
||||
@@ -367,7 +364,6 @@ public class DeviceProfile {
|
||||
extraHotseatBottomPadding = Math.round(paddingHotseatBottom * iconScale);
|
||||
|
||||
hotseatBarSizePx += extraHotseatBottomPadding;
|
||||
hotseatBarBottomPaddingPx += extraHotseatBottomPadding;
|
||||
} else if (!isVerticalBarLayout() && isPhone && isTallDevice) {
|
||||
// We increase the hotseat size when there is extra space.
|
||||
// ie. For a display with a large aspect ratio, we can keep the icons on the workspace
|
||||
@@ -376,7 +372,6 @@ public class DeviceProfile {
|
||||
int extraSpace = getCellSize().y - iconSizePx - iconDrawablePaddingPx * 2
|
||||
- workspacePageIndicatorHeight;
|
||||
hotseatBarSizePx += extraSpace;
|
||||
hotseatBarBottomPaddingPx += extraSpace;
|
||||
|
||||
// Recalculate the available dimensions using the new hotseat size.
|
||||
updateAvailableDimensions(res);
|
||||
@@ -393,6 +388,17 @@ public class DeviceProfile {
|
||||
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
|
||||
}
|
||||
|
||||
private void updateHotseatIconSize(int hotseatIconSizePx) {
|
||||
hotseatCellHeightPx = hotseatIconSizePx;
|
||||
if (isVerticalBarLayout()) {
|
||||
hotseatBarSizePx = hotseatIconSizePx + hotseatBarSidePaddingStartPx
|
||||
+ hotseatBarSidePaddingEndPx;
|
||||
} else {
|
||||
hotseatBarSizePx = hotseatIconSizePx + hotseatBarTopPaddingPx
|
||||
+ hotseatBarBottomPaddingPx + (isScalableGrid ? 0 : hotseatExtraVerticalSize);
|
||||
}
|
||||
}
|
||||
|
||||
private void setCellLayoutBorderSpacing(int borderSpacing) {
|
||||
cellLayoutBorderSpacingPx = isScalableGrid ? borderSpacing : 0;
|
||||
}
|
||||
@@ -578,11 +584,7 @@ public class DeviceProfile {
|
||||
}
|
||||
|
||||
// Hotseat
|
||||
if (isVerticalLayout) {
|
||||
hotseatBarSizePx = iconSizePx + hotseatBarSidePaddingStartPx
|
||||
+ hotseatBarSidePaddingEndPx;
|
||||
}
|
||||
hotseatCellHeightPx = iconSizePx;
|
||||
updateHotseatIconSize(iconSizePx);
|
||||
|
||||
if (!isVerticalLayout) {
|
||||
int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx
|
||||
@@ -795,7 +797,8 @@ public class DeviceProfile {
|
||||
hotseatBarTopPaddingPx,
|
||||
hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx
|
||||
+ mInsets.right,
|
||||
hotseatBarBottomPaddingPx + mInsets.bottom + cellLayoutBottomPaddingPx);
|
||||
hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
|
||||
+ cellLayoutBottomPaddingPx + mInsets.bottom);
|
||||
}
|
||||
return mHotseatPadding;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,9 @@ public class ExtendedEditText extends EditText {
|
||||
}
|
||||
}
|
||||
|
||||
// inherited class can override to change the appearance of the edit text.
|
||||
public void show() {}
|
||||
|
||||
public void showKeyboard() {
|
||||
mShowImeAfterFirstLayout = !showSoftInput();
|
||||
}
|
||||
|
||||
@@ -1080,7 +1080,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
||||
if (ALL_APPS.equals(mPrevLauncherState) && !ALL_APPS.equals(state)
|
||||
// Making sure mAllAppsSessionLogId is not null to avoid double logging.
|
||||
&& mAllAppsSessionLogId != null) {
|
||||
getAppsView().getSearchUiManager().resetSearch();
|
||||
getAppsView().reset(false);
|
||||
getStatsLogManager().logger()
|
||||
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
|
||||
.setWorkspace(
|
||||
|
||||
@@ -138,12 +138,14 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon.
|
||||
mBorderSpacing, null);
|
||||
// Center the icon/folder
|
||||
int cHeight = getCellContentHeight();
|
||||
int cellPaddingY = (int) Math.max(0, ((lp.height - cHeight) / 2f));
|
||||
int cellPaddingY = dp.isScalableGrid && mContainerType == WORKSPACE
|
||||
? dp.cellYPaddingPx
|
||||
: (int) Math.max(0, ((lp.height - cHeight) / 2f));
|
||||
|
||||
// No need to add padding when cell layout border spacing is present.
|
||||
boolean noPadding = (dp.cellLayoutBorderSpacingPx > 0 && mContainerType == WORKSPACE)
|
||||
boolean noPaddingX = (dp.cellLayoutBorderSpacingPx > 0 && mContainerType == WORKSPACE)
|
||||
|| (dp.folderCellLayoutBorderSpacingPx > 0 && mContainerType == FOLDER);
|
||||
int cellPaddingX = noPadding
|
||||
int cellPaddingX = noPaddingX
|
||||
? 0
|
||||
: mContainerType == WORKSPACE
|
||||
? dp.workspaceCellPaddingXPx
|
||||
|
||||
@@ -2836,7 +2836,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
}
|
||||
} else if (mDragInfo != null) {
|
||||
// When drag is cancelled, reattach content view back to its original parent.
|
||||
if (mDragInfo.cell instanceof LauncherAppWidgetHostView) {
|
||||
if (mDragInfo.cell instanceof LauncherAppWidgetHostView && d.dragView != null) {
|
||||
d.dragView.detachContentView(/* reattachToPreviousParent= */ true);
|
||||
}
|
||||
final CellLayout cellLayout = mLauncher.getCellLayout(
|
||||
|
||||
@@ -255,7 +255,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
mWorkModeSwitch.updateCurrentState(isEnabled);
|
||||
}
|
||||
mWorkAdapterProvider.updateCurrentState(isEnabled);
|
||||
mAH[AdapterHolder.WORK].applyPadding();
|
||||
}
|
||||
|
||||
private void hideInput() {
|
||||
@@ -509,7 +508,10 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
R.layout.work_mode_fab, this, false);
|
||||
this.addView(mWorkModeSwitch);
|
||||
mWorkModeSwitch.setInsets(mInsets);
|
||||
mWorkModeSwitch.post(this::resetWorkProfile);
|
||||
mWorkModeSwitch.post(() -> {
|
||||
mAH[AdapterHolder.WORK].applyPadding();
|
||||
resetWorkProfile();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,6 +635,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
mSearchModeWhileUsingTabs = true;
|
||||
rebindAdapters(false); // hide tabs
|
||||
}
|
||||
mHeader.setCollapsed(true);
|
||||
}
|
||||
|
||||
public void onClearSearchResult() {
|
||||
@@ -715,8 +718,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
|
||||
int bottom = mUsingTabs && mHeader.mHeaderCollapsed ? mHeader.getVisibleBottomBound()
|
||||
: mSearchContainer.getBottom();
|
||||
canvas.drawRect(0, 0, getWidth(), bottom + getTranslationY(),
|
||||
canvas.drawRect(0, 0, canvas.getWidth(), bottom + getTranslationY(),
|
||||
mHeaderPaint);
|
||||
|
||||
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && getTranslationY() == 0) {
|
||||
mSearchUiManager.getEditText().setBackground(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +790,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
int bottomOffset = mWorkModeSwitch != null && mIsWork ? switchH : 0;
|
||||
recyclerView.setPadding(padding.left, padding.top, padding.right,
|
||||
padding.bottom + bottomOffset);
|
||||
recyclerView.scrollToTop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,6 +811,9 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
getSearchView().setBackgroundColor(viewBG);
|
||||
getFloatingHeaderView().setHeaderColor(viewBG);
|
||||
invalidateHeader();
|
||||
if (scrolledOffset == 0 && mSearchUiManager.getEditText() != null) {
|
||||
mSearchUiManager.getEditText().show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +188,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
|
||||
StatsLogManager mgr = BaseDraggingActivity.fromContext(getContext()).getStatsLogManager();
|
||||
switch (state) {
|
||||
case SCROLL_STATE_DRAGGING:
|
||||
requestFocus();
|
||||
mgr.logger().sendToInteractionJankMonitor(
|
||||
LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this);
|
||||
break;
|
||||
|
||||
@@ -78,6 +78,9 @@ public final class FeatureFlags {
|
||||
public static final BooleanFlag UNSTABLE_SPRINGS = getDebugFlag(
|
||||
"UNSTABLE_SPRINGS", false, "Enable unstable springs for quickstep animations");
|
||||
|
||||
public static final BooleanFlag ENABLE_LOCAL_COLOR_POPUPS = getDebugFlag(
|
||||
"ENABLE_LOCAL_COLOR_POPUPS", false, "Enable local color extraction for popups.");
|
||||
|
||||
public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
|
||||
"KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
|
||||
|
||||
@@ -248,7 +251,7 @@ public final class FeatureFlags {
|
||||
"Enables scrim over wallpaper for text protection.");
|
||||
|
||||
public static final BooleanFlag WIDGETS_IN_LAUNCHER_PREVIEW = getDebugFlag(
|
||||
"WIDGETS_IN_LAUNCHER_PREVIEW", false,
|
||||
"WIDGETS_IN_LAUNCHER_PREVIEW", true,
|
||||
"Enables widgets in Launcher preview for the Wallpaper app.");
|
||||
|
||||
public static void initialize(Context context) {
|
||||
|
||||
@@ -245,9 +245,8 @@ public class FolderAnimationManager {
|
||||
+ mDeviceProfile.folderCellHeightPx * 2;
|
||||
int page = mIsOpening ? mContent.getCurrentPage() : mContent.getDestinationPage();
|
||||
int left = mContent.getPaddingLeft() + page * lp.width;
|
||||
Rect contentStart = new Rect(0, 0, width, height);
|
||||
Rect contentEnd = new Rect(endRect.left + left, endRect.top, endRect.right + left,
|
||||
endRect.bottom);
|
||||
Rect contentStart = new Rect(left, 0, left + width, height);
|
||||
Rect contentEnd = new Rect(left, 0, left + lp.width, lp.height);
|
||||
play(a, getShape().createRevealAnimator(
|
||||
mFolder.getContent(), contentStart, contentEnd, finalRadius, !mIsOpening));
|
||||
|
||||
|
||||
@@ -174,8 +174,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
folder.setFolderIcon(icon);
|
||||
folder.bind(folderInfo);
|
||||
icon.setFolder(folder);
|
||||
icon.mBackground.paddingY = icon.isInHotseat()
|
||||
? 0 : activityContext.getDeviceProfile().cellYPaddingPx;
|
||||
return icon;
|
||||
}
|
||||
|
||||
@@ -217,7 +215,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
|
||||
icon.setAccessibilityDelegate(activity.getAccessibilityDelegate());
|
||||
|
||||
icon.mBackground.paddingY = icon.isInHotseat() ? 0 : grid.cellYPaddingPx;
|
||||
icon.mPreviewVerifier = new FolderGridOrganizer(activity.getDeviceProfile().inv);
|
||||
icon.mPreviewVerifier.setFolderInfo(folderInfo);
|
||||
icon.updatePreviewItems(false);
|
||||
@@ -579,7 +576,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
public void setFolderBackground(PreviewBackground bg) {
|
||||
mBackground = bg;
|
||||
mBackground.setInvalidateDelegate(this);
|
||||
mBackground.paddingY = isInHotseat() ? 0 : mActivity.getDeviceProfile().cellYPaddingPx;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -627,7 +623,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
|
||||
if (!mForceHideDot && ((mDotInfo != null && mDotInfo.hasDot()) || mDotScale > 0)) {
|
||||
Rect iconBounds = mDotParams.iconBounds;
|
||||
BubbleTextView.getIconBounds(this, iconBounds, mActivity.getDeviceProfile().iconSizePx);
|
||||
iconBounds.offset(0, mBackground.paddingY);
|
||||
float iconScale = (float) mBackground.previewSize / iconBounds.width();
|
||||
Utilities.scaleRectAboutCenter(iconBounds, iconScale);
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@ public class PreviewBackground extends CellLayout.DelegatedCellDrawing {
|
||||
int previewSize;
|
||||
int basePreviewOffsetX;
|
||||
int basePreviewOffsetY;
|
||||
int paddingY;
|
||||
|
||||
private CellLayout mDrawingDelegate;
|
||||
|
||||
@@ -161,7 +160,7 @@ public class PreviewBackground extends CellLayout.DelegatedCellDrawing {
|
||||
previewSize = grid.folderIconSizePx;
|
||||
|
||||
basePreviewOffsetX = (availableSpaceX - previewSize) / 2;
|
||||
basePreviewOffsetY = paddingY + topPadding + grid.folderIconOffsetYPx;
|
||||
basePreviewOffsetY = topPadding + grid.folderIconOffsetYPx;
|
||||
|
||||
// Stroke width is 1dp
|
||||
mStrokeWidth = context.getResources().getDisplayMetrics().density;
|
||||
|
||||
@@ -26,6 +26,7 @@ import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Fragment;
|
||||
import android.app.WallpaperColors;
|
||||
import android.appwidget.AppWidgetHost;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
@@ -42,6 +43,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Process;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -87,6 +89,7 @@ import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.BaseLauncherAppWidgetHostView;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHost;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.LocalColorExtractor;
|
||||
import com.android.launcher3.widget.NavigableAppWidgetHostView;
|
||||
import com.android.launcher3.widget.custom.CustomWidgetManager;
|
||||
|
||||
@@ -206,8 +209,12 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
private final Hotseat mHotseat;
|
||||
private final CellLayout mWorkspace;
|
||||
private final AppWidgetHost mAppWidgetHost;
|
||||
private final SparseIntArray mWallpaperColorResources;
|
||||
|
||||
public LauncherPreviewRenderer(Context context,
|
||||
InvariantDeviceProfile idp,
|
||||
WallpaperColors wallpaperColors) {
|
||||
|
||||
public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp) {
|
||||
super(context);
|
||||
mUiHandler = new Handler(Looper.getMainLooper());
|
||||
mContext = context;
|
||||
@@ -260,9 +267,16 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
|
||||
mDp.workspacePadding.bottom);
|
||||
|
||||
mAppWidgetHost = FeatureFlags.WIDGETS_IN_LAUNCHER_PREVIEW.get()
|
||||
? new LauncherPreviewAppWidgetHost(context)
|
||||
: null;
|
||||
if (FeatureFlags.WIDGETS_IN_LAUNCHER_PREVIEW.get()) {
|
||||
mAppWidgetHost = new LauncherPreviewAppWidgetHost(context);
|
||||
mWallpaperColorResources = wallpaperColors != null
|
||||
? LocalColorExtractor.newInstance(context)
|
||||
.generateColorsOverride(wallpaperColors)
|
||||
: null;
|
||||
} else {
|
||||
mAppWidgetHost = null;
|
||||
mWallpaperColorResources = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Populate preview and render it. */
|
||||
@@ -507,10 +521,12 @@ public class LauncherPreviewRenderer extends ContextWrapper
|
||||
}
|
||||
}
|
||||
|
||||
private static class LauncherPreviewAppWidgetHostView extends BaseLauncherAppWidgetHostView {
|
||||
|
||||
private class LauncherPreviewAppWidgetHostView extends BaseLauncherAppWidgetHostView {
|
||||
private LauncherPreviewAppWidgetHostView(Context context) {
|
||||
super(context);
|
||||
if (Utilities.ATLEAST_S && mWallpaperColorResources != null) {
|
||||
setColorResources(mWallpaperColorResources);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -209,7 +209,7 @@ public class PreviewSurfaceRenderer {
|
||||
if (mDestroyed) {
|
||||
return;
|
||||
}
|
||||
View view = new LauncherPreviewRenderer(inflationContext, mIdp)
|
||||
View view = new LauncherPreviewRenderer(inflationContext, mIdp, mWallpaperColors)
|
||||
.getRenderedView(dataModel, widgetProviderInfoMap);
|
||||
// This aspect scales the view to fit in the surface and centers it
|
||||
final float scale = Math.min(mWidth / (float) view.getMeasuredWidth(),
|
||||
|
||||
@@ -27,6 +27,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.slice.SliceItem;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
|
||||
import com.android.launcher3.logger.LauncherAtom.FromState;
|
||||
import com.android.launcher3.logger.LauncherAtom.ToState;
|
||||
@@ -599,6 +600,13 @@ public class StatsLogManager implements ResourceBasedOverride {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets logging fields from provided {@link LauncherAtom.Slice}.
|
||||
*/
|
||||
default StatsLogger withSlice(LauncherAtom.Slice slice) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the final message and logs it as {@link EventEnum}.
|
||||
*/
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package com.android.launcher3.popup;
|
||||
|
||||
import static androidx.core.content.ContextCompat.getColorStateList;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCELERATED_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.DECELERATED_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_LOCAL_COLOR_POPUPS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -28,6 +31,7 @@ import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
@@ -133,6 +137,8 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
|
||||
private final String mIterateChildrenTag;
|
||||
|
||||
private final int[] mColors;
|
||||
|
||||
public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
mInflater = LayoutInflater.from(context);
|
||||
@@ -171,9 +177,19 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
|
||||
boolean isAboveAnotherSurface = getTopOpenViewWithType(mLauncher, TYPE_FOLDER) != null
|
||||
|| mLauncher.getStateManager().getState() == LauncherState.ALL_APPS;
|
||||
if (!isAboveAnotherSurface && Utilities.ATLEAST_S) {
|
||||
if (!isAboveAnotherSurface && Utilities.ATLEAST_S && ENABLE_LOCAL_COLOR_POPUPS.get()) {
|
||||
setupColorExtraction();
|
||||
}
|
||||
|
||||
if (isAboveAnotherSurface) {
|
||||
mColors = new int[] {
|
||||
getColorStateList(context, R.color.popup_color_first).getDefaultColor()};
|
||||
} else {
|
||||
mColors = new int[] {
|
||||
getColorStateList(context, R.color.popup_color_first).getDefaultColor(),
|
||||
getColorStateList(context, R.color.popup_color_second).getDefaultColor(),
|
||||
getColorStateList(context, R.color.popup_color_third).getDefaultColor()};
|
||||
}
|
||||
}
|
||||
|
||||
public ArrowPopup(Context context, AttributeSet attrs) {
|
||||
@@ -220,6 +236,16 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
* Set the margins and radius of backgrounds after views are properly ordered.
|
||||
*/
|
||||
public void assignMarginsAndBackgrounds(ViewGroup viewGroup) {
|
||||
assignMarginsAndBackgrounds(viewGroup, Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param backgroundColor When Color.TRANSPARENT, we get color from {@link #mColors}.
|
||||
* Otherwise, we will use this color for all child views.
|
||||
*/
|
||||
private void assignMarginsAndBackgrounds(ViewGroup viewGroup, int backgroundColor) {
|
||||
final boolean getColorFromColorArray = backgroundColor == Color.TRANSPARENT;
|
||||
|
||||
int count = viewGroup.getChildCount();
|
||||
int totalVisibleShortcuts = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -229,8 +255,10 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
}
|
||||
}
|
||||
|
||||
int numVisibleChild = 0;
|
||||
int numVisibleShortcut = 0;
|
||||
View lastView = null;
|
||||
AnimatorSet colorAnimator = new AnimatorSet();
|
||||
for (int i = 0; i < count; i++) {
|
||||
View view = viewGroup.getChildAt(i);
|
||||
if (view.getVisibility() == VISIBLE) {
|
||||
@@ -242,8 +270,14 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
MarginLayoutParams mlp = (MarginLayoutParams) lastView.getLayoutParams();
|
||||
mlp.bottomMargin = 0;
|
||||
|
||||
|
||||
if (getColorFromColorArray) {
|
||||
backgroundColor = mColors[numVisibleChild % mColors.length];
|
||||
}
|
||||
|
||||
if (view instanceof ViewGroup && mIterateChildrenTag.equals(view.getTag())) {
|
||||
assignMarginsAndBackgrounds((ViewGroup) view);
|
||||
assignMarginsAndBackgrounds((ViewGroup) view, backgroundColor);
|
||||
numVisibleChild++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -261,8 +295,22 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
numVisibleShortcut++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ENABLE_LOCAL_COLOR_POPUPS.get()) {
|
||||
setChildColor(view, backgroundColor, colorAnimator);
|
||||
// Arrow color matches the first child or the last child.
|
||||
if (!mIsAboveIcon && numVisibleChild == 0) {
|
||||
mArrowColor = backgroundColor;
|
||||
} else if (mIsAboveIcon) {
|
||||
mArrowColor = backgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
numVisibleChild++;
|
||||
}
|
||||
}
|
||||
|
||||
colorAnimator.setDuration(0).start();
|
||||
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,12 @@ public class OptionsPopupView extends ArrowPopup
|
||||
|
||||
public static OptionsPopupView show(
|
||||
Launcher launcher, RectF targetRect, List<OptionItem> items, boolean shouldAddArrow) {
|
||||
return show(launcher, targetRect, items, shouldAddArrow, 0 /* width */);
|
||||
}
|
||||
|
||||
public static OptionsPopupView show(
|
||||
Launcher launcher, RectF targetRect, List<OptionItem> items, boolean shouldAddArrow,
|
||||
int width) {
|
||||
OptionsPopupView popup = (OptionsPopupView) launcher.getLayoutInflater()
|
||||
.inflate(R.layout.longpress_options_menu, launcher.getDragLayer(), false);
|
||||
popup.mTargetRect = targetRect;
|
||||
@@ -140,6 +146,9 @@ public class OptionsPopupView extends ArrowPopup
|
||||
for (OptionItem item : items) {
|
||||
DeepShortcutView view =
|
||||
(DeepShortcutView) popup.inflateAndAdd(R.layout.system_shortcut, popup);
|
||||
if (width > 0) {
|
||||
view.getLayoutParams().width = width;
|
||||
}
|
||||
view.getIconView().setBackgroundDrawable(item.icon);
|
||||
view.getBubbleText().setText(item.label);
|
||||
view.setOnClickListener(popup);
|
||||
|
||||
@@ -105,9 +105,8 @@ public class SpringRelativeLayout extends RelativeLayout {
|
||||
|
||||
@NonNull @Override
|
||||
protected EdgeEffect createEdgeEffect(RecyclerView view, int direction) {
|
||||
switch (direction) {
|
||||
case DIRECTION_TOP:
|
||||
return new EdgeEffectProxy(getContext(), mEdgeGlowTop);
|
||||
if (direction == DIRECTION_TOP) {
|
||||
return new EdgeEffectProxy(getContext(), mEdgeGlowTop);
|
||||
}
|
||||
return super.createEdgeEffect(view, direction);
|
||||
}
|
||||
|
||||
@@ -160,8 +160,11 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo
|
||||
}
|
||||
}
|
||||
|
||||
this.minSpanX = minSpanX;
|
||||
this.minSpanY = minSpanY;
|
||||
// If minSpanX/Y > spanX/Y, ignore the minSpanX/Y to match the behavior described in
|
||||
// minResizeWidth & minResizeHeight Android documentation. See
|
||||
// https://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo
|
||||
this.minSpanX = Math.min(spanX, minSpanX);
|
||||
this.minSpanY = Math.min(spanY, minSpanY);
|
||||
this.maxSpanX = maxSpanX;
|
||||
this.maxSpanY = maxSpanY;
|
||||
this.mIsMinSizeFulfilled = Math.min(spanX, minSpanX) <= idp.numColumns
|
||||
|
||||
@@ -75,6 +75,14 @@ public class LocalColorExtractor implements ResourceBasedOverride {
|
||||
*/
|
||||
public void applyColorsOverride(Context base, WallpaperColors colors) { }
|
||||
|
||||
/**
|
||||
* Generates color resource overrides from {@link WallpaperColors}.
|
||||
*/
|
||||
@Nullable
|
||||
public SparseIntArray generateColorsOverride(WallpaperColors colors) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a view and returns its rect that can be used by the wallpaper local color extractor.
|
||||
*
|
||||
|
||||
@@ -229,7 +229,7 @@ public abstract class AbstractLauncherUiTest {
|
||||
|
||||
protected TestRule getRulesInsideActivityMonitor() {
|
||||
final RuleChain inner = RuleChain.outerRule(new PortraitLandscapeRunner(this))
|
||||
.around(new FailureWatcher(mDevice));
|
||||
.around(new FailureWatcher(mDevice, mLauncher));
|
||||
|
||||
return TestHelpers.isInLauncherProcess()
|
||||
? RuleChain.outerRule(ShellCommandRule.setDefaultLauncher())
|
||||
@@ -310,7 +310,6 @@ public abstract class AbstractLauncherUiTest {
|
||||
assertEquals("Launcher crashed, pid mismatch:",
|
||||
mLauncherPid, mLauncher.getPid().intValue());
|
||||
}
|
||||
checkDetectedLeaks(mLauncher);
|
||||
} finally {
|
||||
mLauncher.onTestFinish();
|
||||
}
|
||||
@@ -618,5 +617,6 @@ public abstract class AbstractLauncherUiTest {
|
||||
isResumed);
|
||||
}
|
||||
|
||||
protected void onLauncherActivityClose(Launcher launcher) { }
|
||||
protected void onLauncherActivityClose(Launcher launcher) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import android.util.Log;
|
||||
|
||||
import androidx.test.uiautomator.UiDevice;
|
||||
|
||||
import com.android.launcher3.tapl.LauncherInstrumentation;
|
||||
import com.android.launcher3.ui.AbstractLauncherUiTest;
|
||||
|
||||
import org.junit.rules.TestWatcher;
|
||||
import org.junit.runner.Description;
|
||||
|
||||
@@ -16,9 +19,11 @@ import java.io.IOException;
|
||||
public class FailureWatcher extends TestWatcher {
|
||||
private static final String TAG = "FailureWatcher";
|
||||
final private UiDevice mDevice;
|
||||
private final LauncherInstrumentation mLauncher;
|
||||
|
||||
public FailureWatcher(UiDevice device) {
|
||||
public FailureWatcher(UiDevice device, LauncherInstrumentation launcher) {
|
||||
mDevice = device;
|
||||
mLauncher = launcher;
|
||||
}
|
||||
|
||||
private static void dumpViewHierarchy(UiDevice device) {
|
||||
@@ -35,6 +40,12 @@ public class FailureWatcher extends TestWatcher {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void succeeded(Description description) {
|
||||
super.succeeded(description);
|
||||
AbstractLauncherUiTest.checkDetectedLeaks(mLauncher);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void failed(Throwable e, Description description) {
|
||||
onError(mDevice, description, e);
|
||||
|
||||
@@ -75,4 +75,9 @@ public final class AppIcon extends Launchable {
|
||||
protected void expectActivityStartEvents() {
|
||||
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String launchableType() {
|
||||
return "app icon";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ import androidx.test.uiautomator.UiObject2;
|
||||
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Menu item in an app icon menu.
|
||||
*/
|
||||
@@ -51,4 +49,9 @@ public class AppIconMenuItem extends Launchable {
|
||||
protected void expectActivityStartEvents() {
|
||||
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String launchableType() {
|
||||
return "app icon menu item";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer {
|
||||
}
|
||||
|
||||
protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
|
||||
return false;
|
||||
return mLauncher.isTablet();
|
||||
}
|
||||
|
||||
protected void goToOverviewUnchecked() {
|
||||
|
||||
@@ -53,23 +53,29 @@ abstract class Launchable {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -504,7 +504,7 @@ public final class LauncherInstrumentation {
|
||||
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)));
|
||||
}
|
||||
|
||||
@@ -46,4 +46,9 @@ public final class Widget extends Launchable {
|
||||
protected void addExpectedEventsForLongClick() {
|
||||
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String launchableType() {
|
||||
return "widget";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user