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