1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.uioverrides.states; 17 18 import static com.android.app.animation.Interpolators.DECELERATE_2; 19 import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation; 20 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS; 21 22 import android.content.Context; 23 24 import com.android.internal.jank.Cuj; 25 import com.android.launcher3.DeviceProfile; 26 import com.android.launcher3.Launcher; 27 import com.android.launcher3.LauncherState; 28 import com.android.launcher3.R; 29 import com.android.launcher3.config.FeatureFlags; 30 import com.android.launcher3.util.Themes; 31 import com.android.launcher3.views.ActivityContext; 32 import com.android.quickstep.util.BaseDepthController; 33 import com.android.systemui.shared.system.InteractionJankMonitorWrapper; 34 35 import java.util.concurrent.TimeUnit; 36 37 /** 38 * Definition for AllApps state 39 */ 40 public class AllAppsState extends LauncherState { 41 42 private static final int STATE_FLAGS = 43 FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS | FLAG_HOTSEAT_INACCESSIBLE; 44 private static final long BACK_CUJ_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5); 45 46 AllAppsState(int id)47 public AllAppsState(int id) { 48 super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS); 49 } 50 51 @Override 52 public <DEVICE_PROFILE_CONTEXT extends Context & ActivityContext> getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState)53 int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState) { 54 return isToState 55 ? context.getDeviceProfile().allAppsOpenDuration 56 : context.getDeviceProfile().allAppsCloseDuration; 57 } 58 59 @Override onBackStarted(Launcher launcher)60 public void onBackStarted(Launcher launcher) { 61 // Because the back gesture can take longer time depending on when user release the finger, 62 // we pass BACK_CUJ_TIMEOUT_MS as timeout to the jank monitor. 63 InteractionJankMonitorWrapper.begin(launcher.getAppsView(), 64 Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK, BACK_CUJ_TIMEOUT_MS); 65 super.onBackStarted(launcher); 66 } 67 68 @Override onBackInvoked(Launcher launcher)69 public void onBackInvoked(Launcher launcher) { 70 // In predictive back swipe, onBackInvoked() will be called after onBackStarted(). 71 // In 3 button mode, onBackStarted() is not called but onBackInvoked() will be called. 72 // Thus In onBackInvoked(), we should only begin instrumenting if we didn't call 73 // onBackStarted() to start instrumenting CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK. 74 if (!InteractionJankMonitorWrapper.isInstrumenting(Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK)) { 75 InteractionJankMonitorWrapper.begin( 76 launcher.getAppsView(), Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK); 77 } 78 super.onBackInvoked(launcher); 79 } 80 81 /** Called when predictive back swipe is cancelled. */ 82 @Override onBackCancelled(Launcher launcher)83 public void onBackCancelled(Launcher launcher) { 84 super.onBackCancelled(launcher); 85 InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK); 86 } 87 88 @Override onBackAnimationCompleted(boolean success)89 protected void onBackAnimationCompleted(boolean success) { 90 if (success) { 91 // Animation was successful. 92 InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK); 93 } else { 94 // Animation was canceled. 95 InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK); 96 } 97 } 98 99 @Override getDescription(Launcher launcher)100 public String getDescription(Launcher launcher) { 101 return launcher.getAppsView().getDescription(); 102 } 103 104 @Override getTitle()105 public int getTitle() { 106 return R.string.all_apps_label; 107 } 108 109 @Override getVerticalProgress(Launcher launcher)110 public float getVerticalProgress(Launcher launcher) { 111 return 0f; 112 } 113 114 @Override getWorkspaceScaleAndTranslation(Launcher launcher)115 public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) { 116 return new ScaleAndTranslation(launcher.getDeviceProfile().workspaceContentScale, NO_OFFSET, 117 NO_OFFSET); 118 } 119 120 @Override getHotseatScaleAndTranslation(Launcher launcher)121 public ScaleAndTranslation getHotseatScaleAndTranslation(Launcher launcher) { 122 if (launcher.getDeviceProfile().isTablet) { 123 return getWorkspaceScaleAndTranslation(launcher); 124 } else { 125 ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW 126 .getWorkspaceScaleAndTranslation(launcher); 127 return new ScaleAndTranslation( 128 launcher.getDeviceProfile().workspaceContentScale, 129 overviewScaleAndTranslation.translationX, 130 overviewScaleAndTranslation.translationY); 131 } 132 } 133 134 @Override 135 protected <DEVICE_PROFILE_CONTEXT extends Context & ActivityContext> getDepthUnchecked(DEVICE_PROFILE_CONTEXT context)136 float getDepthUnchecked(DEVICE_PROFILE_CONTEXT context) { 137 if (context.getDeviceProfile().isTablet) { 138 return context.getDeviceProfile().bottomSheetDepth; 139 } else { 140 // The scrim fades in at approximately 50% of the swipe gesture. 141 if (enableScalingRevealHomeAnimation()) { 142 // This means that the depth should be twice of what we want, in order to fully zoom 143 // out during the visible portion of the animation. 144 return BaseDepthController.DEPTH_60_PERCENT; 145 } else { 146 // This means that the depth should be greater than 1, in order to fully zoom out. 147 return 2f; 148 } 149 } 150 } 151 152 @Override getWorkspacePageAlphaProvider(Launcher launcher)153 public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) { 154 PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher); 155 return new PageAlphaProvider(DECELERATE_2) { 156 @Override 157 public float getPageAlpha(int pageIndex) { 158 return launcher.getDeviceProfile().isTablet 159 ? superPageAlphaProvider.getPageAlpha(pageIndex) 160 : 0; 161 } 162 }; 163 } 164 165 @Override 166 public int getVisibleElements(Launcher launcher) { 167 int elements = ALL_APPS_CONTENT | FLOATING_SEARCH_BAR; 168 // Only add HOTSEAT_ICONS for tablets in ALL_APPS state. 169 if (launcher.getDeviceProfile().isTablet) { 170 elements |= HOTSEAT_ICONS; 171 } 172 return elements; 173 } 174 175 @Override 176 public int getFloatingSearchBarRestingMarginBottom(Launcher launcher) { 177 return 0; 178 } 179 180 @Override 181 public int getFloatingSearchBarRestingMarginStart(Launcher launcher) { 182 DeviceProfile dp = launcher.getDeviceProfile(); 183 return dp.allAppsLeftRightMargin + dp.getAllAppsIconStartMargin(launcher); 184 } 185 186 @Override 187 public int getFloatingSearchBarRestingMarginEnd(Launcher launcher) { 188 DeviceProfile dp = launcher.getDeviceProfile(); 189 return dp.allAppsLeftRightMargin + dp.getAllAppsIconStartMargin(launcher); 190 } 191 192 @Override 193 public boolean shouldFloatingSearchBarUsePillWhenUnfocused(Launcher launcher) { 194 DeviceProfile dp = launcher.getDeviceProfile(); 195 return dp.isPhone && !dp.isLandscape; 196 } 197 198 @Override 199 public LauncherState getHistoryForState(LauncherState previousState) { 200 return previousState == BACKGROUND_APP ? QUICK_SWITCH_FROM_HOME 201 : previousState == OVERVIEW ? OVERVIEW : NORMAL; 202 } 203 204 @Override 205 public float[] getOverviewScaleAndOffset(Launcher launcher) { 206 if (!FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()) { 207 return super.getOverviewScaleAndOffset(launcher); 208 } 209 // This handles the case of returning to the previous app from Overview -> All Apps gesture. 210 // This is the start scale/offset of overview that will be used for that transition. 211 // TODO (b/283336332): Translate in Y direction (ideally with overview resistance). 212 return new float[] {0.5f /* scale */, NO_OFFSET}; 213 } 214 215 @Override 216 public int getWorkspaceScrimColor(Launcher launcher) { 217 return launcher.getDeviceProfile().isTablet 218 ? launcher.getResources().getColor(R.color.widgets_picker_scrim) 219 : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor); 220 } 221 } 222