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