Home | History | Annotate | Download | only in recents
      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 
     17 package com.android.systemui.recents;
     18 
     19 import android.app.ActivityManager;
     20 import android.content.Context;
     21 import android.content.res.Configuration;
     22 import android.content.res.Resources;
     23 import android.graphics.Rect;
     24 import android.provider.Settings;
     25 import android.util.DisplayMetrics;
     26 import android.view.animation.AnimationUtils;
     27 import android.view.animation.Interpolator;
     28 
     29 import com.android.systemui.Prefs;
     30 import com.android.systemui.R;
     31 import com.android.systemui.recents.misc.Console;
     32 import 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 */
     37 public class RecentsConfiguration {
     38     static RecentsConfiguration sInstance;
     39     static int sPrevConfigurationHashCode;
     40 
     41     /** Levels of svelte in increasing severity/austerity. */
     42     // No svelting.
     43     public static final int SVELTE_NONE = 0;
     44     // Limit thumbnail cache to number of visible thumbnails when Recents was loaded, disable
     45     // caching thumbnails as you scroll.
     46     public static final int SVELTE_LIMIT_CACHE = 1;
     47     // Disable the thumbnail cache, load thumbnails asynchronously when the activity loads and
     48     // evict all thumbnails when hidden.
     49     public static final int SVELTE_DISABLE_CACHE = 2;
     50     // Disable all thumbnail loading.
     51     public static final int SVELTE_DISABLE_LOADING = 3;
     52 
     53     /** Interpolators */
     54     public Interpolator fastOutSlowInInterpolator;
     55     public Interpolator fastOutLinearInInterpolator;
     56     public Interpolator linearOutSlowInInterpolator;
     57     public Interpolator quintOutInterpolator;
     58 
     59     /** Filtering */
     60     public int filteringCurrentViewsAnimDuration;
     61     public int filteringNewViewsAnimDuration;
     62 
     63     /** Insets */
     64     public Rect systemInsets = new Rect();
     65     public Rect displayRect = new Rect();
     66 
     67     /** Layout */
     68     boolean isLandscape;
     69     boolean hasTransposedSearchBar;
     70     boolean hasTransposedNavBar;
     71 
     72     /** Loading */
     73     public int maxNumTasksToLoad;
     74 
     75     /** Search bar */
     76     public int searchBarSpaceHeightPx;
     77 
     78     /** Task stack */
     79     public int taskStackScrollDuration;
     80     public int taskStackMaxDim;
     81     public int taskStackTopPaddingPx;
     82     public int dismissAllButtonSizePx;
     83     public float taskStackWidthPaddingPct;
     84     public float taskStackOverscrollPct;
     85 
     86     /** Transitions */
     87     public int transitionEnterFromAppDelay;
     88     public int transitionEnterFromHomeDelay;
     89 
     90     /** Task view animation and styles */
     91     public int taskViewEnterFromAppDuration;
     92     public int taskViewEnterFromHomeDuration;
     93     public int taskViewEnterFromHomeStaggerDelay;
     94     public int taskViewExitToAppDuration;
     95     public int taskViewExitToHomeDuration;
     96     public int taskViewRemoveAnimDuration;
     97     public int taskViewRemoveAnimTranslationXPx;
     98     public int taskViewTranslationZMinPx;
     99     public int taskViewTranslationZMaxPx;
    100     public int taskViewRoundedCornerRadiusPx;
    101     public int taskViewHighlightPx;
    102     public int taskViewAffiliateGroupEnterOffsetPx;
    103     public float taskViewThumbnailAlpha;
    104 
    105     /** Task bar colors */
    106     public int taskBarViewDefaultBackgroundColor;
    107     public int taskBarViewLightTextColor;
    108     public int taskBarViewDarkTextColor;
    109     public int taskBarViewHighlightColor;
    110     public float taskBarViewAffiliationColorMinAlpha;
    111 
    112     /** Task bar size & animations */
    113     public int taskBarHeight;
    114     public int taskBarDismissDozeDelaySeconds;
    115 
    116     /** Nav bar scrim */
    117     public int navBarScrimEnterDuration;
    118 
    119     /** Launch states */
    120     public boolean launchedWithAltTab;
    121     public boolean launchedWithNoRecentTasks;
    122     public boolean launchedFromAppWithThumbnail;
    123     public boolean launchedFromHome;
    124     public boolean launchedFromSearchHome;
    125     public boolean launchedReuseTaskStackViews;
    126     public boolean launchedHasConfigurationChanged;
    127     public int launchedToTaskId;
    128     public int launchedNumVisibleTasks;
    129     public int launchedNumVisibleThumbnails;
    130 
    131     /** Misc **/
    132     public boolean useHardwareLayers;
    133     public int altTabKeyDelay;
    134     public boolean fakeShadows;
    135 
    136     /** Dev options and global settings */
    137     public boolean multiStackEnabled;
    138     public boolean lockToAppEnabled;
    139     public boolean developerOptionsEnabled;
    140     public boolean debugModeEnabled;
    141     public int svelteLevel;
    142 
    143     /** Private constructor */
    144     private RecentsConfiguration(Context context) {
    145         // Properties that don't have to be reloaded with each configuration change can be loaded
    146         // here.
    147 
    148         // Interpolators
    149         fastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
    150                 com.android.internal.R.interpolator.fast_out_slow_in);
    151         fastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
    152                 com.android.internal.R.interpolator.fast_out_linear_in);
    153         linearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
    154                 com.android.internal.R.interpolator.linear_out_slow_in);
    155         quintOutInterpolator = AnimationUtils.loadInterpolator(context,
    156                 com.android.internal.R.interpolator.decelerate_quint);
    157     }
    158 
    159     /** Updates the configuration to the current context */
    160     public static RecentsConfiguration reinitialize(Context context, SystemServicesProxy ssp) {
    161         if (sInstance == null) {
    162             sInstance = new RecentsConfiguration(context);
    163         }
    164         int configHashCode = context.getResources().getConfiguration().hashCode();
    165         if (sPrevConfigurationHashCode != configHashCode) {
    166             sInstance.update(context);
    167             sPrevConfigurationHashCode = configHashCode;
    168         }
    169         sInstance.updateOnReinitialize(context, ssp);
    170         return sInstance;
    171     }
    172 
    173     /** Returns the current recents configuration */
    174     public static RecentsConfiguration getInstance() {
    175         return sInstance;
    176     }
    177 
    178     /** Updates the state, given the specified context */
    179     void update(Context context) {
    180         Resources res = context.getResources();
    181         DisplayMetrics dm = res.getDisplayMetrics();
    182 
    183         // Debug mode
    184         debugModeEnabled = Prefs.getBoolean(context, Prefs.Key.DEBUG_MODE_ENABLED,
    185                 false /* defaultValue */);
    186         if (debugModeEnabled) {
    187             Console.Enabled = true;
    188         }
    189 
    190         // Layout
    191         isLandscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
    192         hasTransposedSearchBar = res.getBoolean(R.bool.recents_has_transposed_search_bar);
    193         hasTransposedNavBar = res.getBoolean(R.bool.recents_has_transposed_nav_bar);
    194 
    195         // Insets
    196         displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
    197 
    198         // Filtering
    199         filteringCurrentViewsAnimDuration =
    200                 res.getInteger(R.integer.recents_filter_animate_current_views_duration);
    201         filteringNewViewsAnimDuration =
    202                 res.getInteger(R.integer.recents_filter_animate_new_views_duration);
    203 
    204         // Loading
    205         maxNumTasksToLoad = ActivityManager.getMaxRecentTasksStatic();
    206 
    207         // Search Bar
    208         searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
    209 
    210         // Task stack
    211         taskStackScrollDuration =
    212                 res.getInteger(R.integer.recents_animate_task_stack_scroll_duration);
    213         taskStackWidthPaddingPct = res.getFloat(R.dimen.recents_stack_width_padding_percentage);
    214         taskStackOverscrollPct = res.getFloat(R.dimen.recents_stack_overscroll_percentage);
    215         taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
    216         taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
    217         dismissAllButtonSizePx = res.getDimensionPixelSize(R.dimen.recents_dismiss_all_button_size);
    218 
    219         // Transition
    220         transitionEnterFromAppDelay =
    221                 res.getInteger(R.integer.recents_enter_from_app_transition_duration);
    222         transitionEnterFromHomeDelay =
    223                 res.getInteger(R.integer.recents_enter_from_home_transition_duration);
    224 
    225         // Task view animation and styles
    226         taskViewEnterFromAppDuration =
    227                 res.getInteger(R.integer.recents_task_enter_from_app_duration);
    228         taskViewEnterFromHomeDuration =
    229                 res.getInteger(R.integer.recents_task_enter_from_home_duration);
    230         taskViewEnterFromHomeStaggerDelay =
    231                 res.getInteger(R.integer.recents_task_enter_from_home_stagger_delay);
    232         taskViewExitToAppDuration =
    233                 res.getInteger(R.integer.recents_task_exit_to_app_duration);
    234         taskViewExitToHomeDuration =
    235                 res.getInteger(R.integer.recents_task_exit_to_home_duration);
    236         taskViewRemoveAnimDuration =
    237                 res.getInteger(R.integer.recents_animate_task_view_remove_duration);
    238         taskViewRemoveAnimTranslationXPx =
    239                 res.getDimensionPixelSize(R.dimen.recents_task_view_remove_anim_translation_x);
    240         taskViewRoundedCornerRadiusPx =
    241                 res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
    242         taskViewHighlightPx = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
    243         taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
    244         taskViewTranslationZMaxPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
    245         taskViewAffiliateGroupEnterOffsetPx =
    246                 res.getDimensionPixelSize(R.dimen.recents_task_view_affiliate_group_enter_offset);
    247         taskViewThumbnailAlpha = res.getFloat(R.dimen.recents_task_view_thumbnail_alpha);
    248 
    249         // Task bar colors
    250         taskBarViewDefaultBackgroundColor = context.getColor(
    251                 R.color.recents_task_bar_default_background_color);
    252         taskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
    253         taskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
    254         taskBarViewHighlightColor = context.getColor(R.color.recents_task_bar_highlight_color);
    255         taskBarViewAffiliationColorMinAlpha = res.getFloat(
    256                 R.dimen.recents_task_affiliation_color_min_alpha_percentage);
    257 
    258         // Task bar size & animations
    259         taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
    260         taskBarDismissDozeDelaySeconds =
    261                 res.getInteger(R.integer.recents_task_bar_dismiss_delay_seconds);
    262 
    263         // Nav bar scrim
    264         navBarScrimEnterDuration =
    265                 res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
    266 
    267         // Misc
    268         useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
    269         altTabKeyDelay = res.getInteger(R.integer.recents_alt_tab_key_delay);
    270         fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
    271         svelteLevel = res.getInteger(R.integer.recents_svelte_level);
    272     }
    273 
    274     /** Updates the system insets */
    275     public void updateSystemInsets(Rect insets) {
    276         systemInsets.set(insets);
    277     }
    278 
    279     /** Updates the states that need to be re-read whenever we re-initialize. */
    280     void updateOnReinitialize(Context context, SystemServicesProxy ssp) {
    281         // Check if the developer options are enabled
    282         developerOptionsEnabled = ssp.getGlobalSetting(context,
    283                 Settings.Global.DEVELOPMENT_SETTINGS_ENABLED) != 0;
    284         lockToAppEnabled = ssp.getSystemSetting(context,
    285                 Settings.System.LOCK_TO_APP_ENABLED) != 0;
    286         multiStackEnabled = "true".equals(ssp.getSystemProperty("persist.sys.debug.multi_window"));
    287     }
    288 
    289     /** Called when the configuration has changed, and we want to reset any configuration specific
    290      * members. */
    291     public void updateOnConfigurationChange() {
    292         // Reset this flag on configuration change to ensure that we recreate new task views
    293         launchedReuseTaskStackViews = false;
    294         // Set this flag to indicate that the configuration has changed since Recents last launched
    295         launchedHasConfigurationChanged = true;
    296     }
    297 
    298     /** Returns whether the status bar scrim should be animated when shown for the first time. */
    299     public boolean shouldAnimateStatusBarScrim() {
    300         return launchedFromHome;
    301     }
    302 
    303     /** Returns whether the status bar scrim should be visible. */
    304     public boolean hasStatusBarScrim() {
    305         return !launchedWithNoRecentTasks;
    306     }
    307 
    308     /** Returns whether the nav bar scrim should be animated when shown for the first time. */
    309     public boolean shouldAnimateNavBarScrim() {
    310         return true;
    311     }
    312 
    313     /** Returns whether the nav bar scrim should be visible. */
    314     public boolean hasNavBarScrim() {
    315         // Only show the scrim if we have recent tasks, and if the nav bar is not transposed
    316         return !launchedWithNoRecentTasks && (!hasTransposedNavBar || !isLandscape);
    317     }
    318 
    319     /**
    320      * Returns the task stack bounds in the current orientation. These bounds do not account for
    321      * the system insets.
    322      */
    323     public void getAvailableTaskStackBounds(int windowWidth, int windowHeight, int topInset,
    324             int rightInset, Rect searchBarBounds, Rect taskStackBounds) {
    325         if (isLandscape && hasTransposedSearchBar) {
    326             // In landscape, the search bar appears on the left, but we overlay it on top
    327             taskStackBounds.set(0, topInset, windowWidth - rightInset, windowHeight);
    328         } else {
    329             // In portrait, the search bar appears on the top (which already has the inset)
    330             taskStackBounds.set(0, searchBarBounds.bottom, windowWidth, windowHeight);
    331         }
    332     }
    333 
    334     /**
    335      * Returns the search bar bounds in the current orientation.  These bounds do not account for
    336      * the system insets.
    337      */
    338     public void getSearchBarBounds(int windowWidth, int windowHeight, int topInset,
    339             Rect searchBarSpaceBounds) {
    340         // Return empty rects if search is not enabled
    341         int searchBarSize = searchBarSpaceHeightPx;
    342         if (isLandscape && hasTransposedSearchBar) {
    343             // In landscape, the search bar appears on the left
    344             searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight);
    345         } else {
    346             // In portrait, the search bar appears on the top
    347             searchBarSpaceBounds.set(0, topInset, windowWidth, topInset + searchBarSize);
    348         }
    349     }
    350 }
    351