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