RecentsConfiguration.java revision 82862573bcf246128782b91ea627285c43133a8d
1/* 2 * Copyright (C) 2014 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 17package com.android.systemui.recents; 18 19import android.app.ActivityManager; 20import android.content.Context; 21import android.content.res.Configuration; 22import android.content.res.Resources; 23import android.graphics.Rect; 24import android.provider.Settings; 25import android.util.DisplayMetrics; 26import android.view.animation.AnimationUtils; 27import android.view.animation.Interpolator; 28 29import com.android.systemui.Prefs; 30import com.android.systemui.R; 31import com.android.systemui.recents.misc.Console; 32import com.android.systemui.recents.misc.SystemServicesProxy; 33 34 35/** A static Recents configuration for the current context 36 * NOTE: We should not hold any references to a Context from a static instance */ 37public class RecentsConfiguration { 38 static RecentsConfiguration sInstance; 39 static int sPrevConfigurationHashCode; 40 41 /** Levels of svelte in increasing severity/austerity. */ 42 // No svelting. 43 public static final int SVELTE_NONE = 0; 44 // Limit thumbnail cache to number of visible thumbnails when Recents was loaded, disable 45 // caching thumbnails as you scroll. 46 public static final int SVELTE_LIMIT_CACHE = 1; 47 // Disable the thumbnail cache, load thumbnails asynchronously when the activity loads and 48 // evict all thumbnails when hidden. 49 public static final int SVELTE_DISABLE_CACHE = 2; 50 // Disable all thumbnail loading. 51 public static final int SVELTE_DISABLE_LOADING = 3; 52 53 /** Interpolators */ 54 public Interpolator fastOutSlowInInterpolator; 55 public Interpolator fastOutLinearInInterpolator; 56 public Interpolator linearOutSlowInInterpolator; 57 public Interpolator quintOutInterpolator; 58 59 /** Filtering */ 60 public int filteringCurrentViewsAnimDuration; 61 public int filteringNewViewsAnimDuration; 62 63 /** Insets */ 64 public Rect systemInsets = new Rect(); 65 public Rect displayRect = new Rect(); 66 67 /** Layout */ 68 boolean isLandscape; 69 boolean hasTransposedSearchBar; 70 boolean hasTransposedNavBar; 71 72 /** Loading */ 73 public int maxNumTasksToLoad; 74 75 /** Search bar */ 76 int searchBarAppWidgetId = -1; 77 public int searchBarSpaceHeightPx; 78 79 /** Task stack */ 80 public int taskStackScrollDuration; 81 public int taskStackMaxDim; 82 public int taskStackTopPaddingPx; 83 public int dismissAllButtonSizePx; 84 public float taskStackWidthPaddingPct; 85 public float taskStackOverscrollPct; 86 87 /** Transitions */ 88 public int transitionEnterFromAppDelay; 89 public int transitionEnterFromHomeDelay; 90 91 /** Task view animation and styles */ 92 public int taskViewEnterFromAppDuration; 93 public int taskViewEnterFromHomeDuration; 94 public int taskViewEnterFromHomeStaggerDelay; 95 public int taskViewExitToAppDuration; 96 public int taskViewExitToHomeDuration; 97 public int taskViewRemoveAnimDuration; 98 public int taskViewRemoveAnimTranslationXPx; 99 public int taskViewTranslationZMinPx; 100 public int taskViewTranslationZMaxPx; 101 public int taskViewRoundedCornerRadiusPx; 102 public int taskViewHighlightPx; 103 public int taskViewAffiliateGroupEnterOffsetPx; 104 public float taskViewThumbnailAlpha; 105 106 /** Task bar colors */ 107 public int taskBarViewDefaultBackgroundColor; 108 public int taskBarViewLightTextColor; 109 public int taskBarViewDarkTextColor; 110 public int taskBarViewHighlightColor; 111 public float taskBarViewAffiliationColorMinAlpha; 112 113 /** Task bar size & animations */ 114 public int taskBarHeight; 115 public int taskBarDismissDozeDelaySeconds; 116 117 /** Nav bar scrim */ 118 public int navBarScrimEnterDuration; 119 120 /** Launch states */ 121 public boolean launchedWithAltTab; 122 public boolean launchedWithNoRecentTasks; 123 public boolean launchedFromAppWithThumbnail; 124 public boolean launchedFromHome; 125 public boolean launchedFromSearchHome; 126 public boolean launchedReuseTaskStackViews; 127 public boolean launchedHasConfigurationChanged; 128 public int launchedToTaskId; 129 public int launchedNumVisibleTasks; 130 public int launchedNumVisibleThumbnails; 131 132 /** Misc **/ 133 public boolean useHardwareLayers; 134 public int altTabKeyDelay; 135 public boolean fakeShadows; 136 137 /** Dev options and global settings */ 138 public boolean multiStackEnabled; 139 public boolean lockToAppEnabled; 140 public boolean developerOptionsEnabled; 141 public boolean debugModeEnabled; 142 public int svelteLevel; 143 144 /** Private constructor */ 145 private RecentsConfiguration(Context context) { 146 // Properties that don't have to be reloaded with each configuration change can be loaded 147 // here. 148 149 // Interpolators 150 fastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, 151 com.android.internal.R.interpolator.fast_out_slow_in); 152 fastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, 153 com.android.internal.R.interpolator.fast_out_linear_in); 154 linearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, 155 com.android.internal.R.interpolator.linear_out_slow_in); 156 quintOutInterpolator = AnimationUtils.loadInterpolator(context, 157 com.android.internal.R.interpolator.decelerate_quint); 158 } 159 160 /** Updates the configuration to the current context */ 161 public static RecentsConfiguration reinitialize(Context context, SystemServicesProxy ssp) { 162 if (sInstance == null) { 163 sInstance = new RecentsConfiguration(context); 164 } 165 int configHashCode = context.getResources().getConfiguration().hashCode(); 166 if (sPrevConfigurationHashCode != configHashCode) { 167 sInstance.update(context); 168 sPrevConfigurationHashCode = configHashCode; 169 } 170 sInstance.updateOnReinitialize(context, ssp); 171 return sInstance; 172 } 173 174 /** Returns the current recents configuration */ 175 public static RecentsConfiguration getInstance() { 176 return sInstance; 177 } 178 179 /** Updates the state, given the specified context */ 180 void update(Context context) { 181 Resources res = context.getResources(); 182 DisplayMetrics dm = res.getDisplayMetrics(); 183 184 // Debug mode 185 debugModeEnabled = Prefs.getBoolean(context, Prefs.Key.DEBUG_MODE_ENABLED, 186 false /* defaultValue */); 187 if (debugModeEnabled) { 188 Console.Enabled = true; 189 } 190 191 // Layout 192 isLandscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; 193 hasTransposedSearchBar = res.getBoolean(R.bool.recents_has_transposed_search_bar); 194 hasTransposedNavBar = res.getBoolean(R.bool.recents_has_transposed_nav_bar); 195 196 // Insets 197 displayRect.set(0, 0, dm.widthPixels, dm.heightPixels); 198 199 // Filtering 200 filteringCurrentViewsAnimDuration = 201 res.getInteger(R.integer.recents_filter_animate_current_views_duration); 202 filteringNewViewsAnimDuration = 203 res.getInteger(R.integer.recents_filter_animate_new_views_duration); 204 205 // Loading 206 maxNumTasksToLoad = ActivityManager.getMaxRecentTasksStatic(); 207 208 // Search Bar 209 searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height); 210 searchBarAppWidgetId = Prefs.getInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, 211 -1 /* defaultValue */); 212 213 // Task stack 214 taskStackScrollDuration = 215 res.getInteger(R.integer.recents_animate_task_stack_scroll_duration); 216 taskStackWidthPaddingPct = res.getFloat(R.dimen.recents_stack_width_padding_percentage); 217 taskStackOverscrollPct = res.getFloat(R.dimen.recents_stack_overscroll_percentage); 218 taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim); 219 taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding); 220 dismissAllButtonSizePx = res.getDimensionPixelSize(R.dimen.recents_dismiss_all_button_size); 221 222 // Transition 223 transitionEnterFromAppDelay = 224 res.getInteger(R.integer.recents_enter_from_app_transition_duration); 225 transitionEnterFromHomeDelay = 226 res.getInteger(R.integer.recents_enter_from_home_transition_duration); 227 228 // Task view animation and styles 229 taskViewEnterFromAppDuration = 230 res.getInteger(R.integer.recents_task_enter_from_app_duration); 231 taskViewEnterFromHomeDuration = 232 res.getInteger(R.integer.recents_task_enter_from_home_duration); 233 taskViewEnterFromHomeStaggerDelay = 234 res.getInteger(R.integer.recents_task_enter_from_home_stagger_delay); 235 taskViewExitToAppDuration = 236 res.getInteger(R.integer.recents_task_exit_to_app_duration); 237 taskViewExitToHomeDuration = 238 res.getInteger(R.integer.recents_task_exit_to_home_duration); 239 taskViewRemoveAnimDuration = 240 res.getInteger(R.integer.recents_animate_task_view_remove_duration); 241 taskViewRemoveAnimTranslationXPx = 242 res.getDimensionPixelSize(R.dimen.recents_task_view_remove_anim_translation_x); 243 taskViewRoundedCornerRadiusPx = 244 res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius); 245 taskViewHighlightPx = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight); 246 taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min); 247 taskViewTranslationZMaxPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max); 248 taskViewAffiliateGroupEnterOffsetPx = 249 res.getDimensionPixelSize(R.dimen.recents_task_view_affiliate_group_enter_offset); 250 taskViewThumbnailAlpha = res.getFloat(R.dimen.recents_task_view_thumbnail_alpha); 251 252 // Task bar colors 253 taskBarViewDefaultBackgroundColor = context.getColor( 254 R.color.recents_task_bar_default_background_color); 255 taskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color); 256 taskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color); 257 taskBarViewHighlightColor = context.getColor(R.color.recents_task_bar_highlight_color); 258 taskBarViewAffiliationColorMinAlpha = res.getFloat( 259 R.dimen.recents_task_affiliation_color_min_alpha_percentage); 260 261 // Task bar size & animations 262 taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height); 263 taskBarDismissDozeDelaySeconds = 264 res.getInteger(R.integer.recents_task_bar_dismiss_delay_seconds); 265 266 // Nav bar scrim 267 navBarScrimEnterDuration = 268 res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration); 269 270 // Misc 271 useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers); 272 altTabKeyDelay = res.getInteger(R.integer.recents_alt_tab_key_delay); 273 fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows); 274 svelteLevel = res.getInteger(R.integer.recents_svelte_level); 275 } 276 277 /** Updates the system insets */ 278 public void updateSystemInsets(Rect insets) { 279 systemInsets.set(insets); 280 } 281 282 /** Updates the search bar app widget */ 283 public void updateSearchBarAppWidgetId(Context context, int appWidgetId) { 284 searchBarAppWidgetId = appWidgetId; 285 Prefs.putInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, appWidgetId); 286 } 287 288 /** Updates the states that need to be re-read whenever we re-initialize. */ 289 void updateOnReinitialize(Context context, SystemServicesProxy ssp) { 290 // Check if the developer options are enabled 291 developerOptionsEnabled = ssp.getGlobalSetting(context, 292 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED) != 0; 293 lockToAppEnabled = ssp.getSystemSetting(context, 294 Settings.System.LOCK_TO_APP_ENABLED) != 0; 295 multiStackEnabled = "true".equals(ssp.getSystemProperty("persist.sys.debug.multi_window")); 296 } 297 298 /** Called when the configuration has changed, and we want to reset any configuration specific 299 * members. */ 300 public void updateOnConfigurationChange() { 301 // Reset this flag on configuration change to ensure that we recreate new task views 302 launchedReuseTaskStackViews = false; 303 // Set this flag to indicate that the configuration has changed since Recents last launched 304 launchedHasConfigurationChanged = true; 305 } 306 307 /** Returns whether the search bar app widget exists. */ 308 public boolean hasSearchBarAppWidget() { 309 return searchBarAppWidgetId >= 0; 310 } 311 312 /** Returns whether the status bar scrim should be animated when shown for the first time. */ 313 public boolean shouldAnimateStatusBarScrim() { 314 return launchedFromHome; 315 } 316 317 /** Returns whether the status bar scrim should be visible. */ 318 public boolean hasStatusBarScrim() { 319 return !launchedWithNoRecentTasks; 320 } 321 322 /** Returns whether the nav bar scrim should be animated when shown for the first time. */ 323 public boolean shouldAnimateNavBarScrim() { 324 return true; 325 } 326 327 /** Returns whether the nav bar scrim should be visible. */ 328 public boolean hasNavBarScrim() { 329 // Only show the scrim if we have recent tasks, and if the nav bar is not transposed 330 return !launchedWithNoRecentTasks && (!hasTransposedNavBar || !isLandscape); 331 } 332 333 /** 334 * Returns the task stack bounds in the current orientation. These bounds do not account for 335 * the system insets. 336 */ 337 public void getAvailableTaskStackBounds(int windowWidth, int windowHeight, int topInset, 338 int rightInset, Rect taskStackBounds) { 339 Rect searchBarBounds = new Rect(); 340 getSearchBarBounds(windowWidth, windowHeight, topInset, searchBarBounds); 341 if (isLandscape && hasTransposedSearchBar) { 342 // In landscape, the search bar appears on the left, but we overlay it on top 343 taskStackBounds.set(0, topInset, windowWidth - rightInset, windowHeight); 344 } else { 345 // In portrait, the search bar appears on the top (which already has the inset) 346 taskStackBounds.set(0, searchBarBounds.bottom, windowWidth, windowHeight); 347 } 348 } 349 350 /** 351 * Returns the search bar bounds in the current orientation. These bounds do not account for 352 * the system insets. 353 */ 354 public void getSearchBarBounds(int windowWidth, int windowHeight, int topInset, 355 Rect searchBarSpaceBounds) { 356 // Return empty rects if search is not enabled 357 int searchBarSize = searchBarSpaceHeightPx; 358 if (!Constants.DebugFlags.App.EnableSearchLayout || !hasSearchBarAppWidget()) { 359 searchBarSize = 0; 360 } 361 362 if (isLandscape && hasTransposedSearchBar) { 363 // In landscape, the search bar appears on the left 364 searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight); 365 } else { 366 // In portrait, the search bar appears on the top 367 searchBarSpaceBounds.set(0, topInset, windowWidth, topInset + searchBarSize); 368 } 369 } 370} 371