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