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