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