• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.launcher3.config;
18 
19 import android.content.Context;
20 
21 import com.android.launcher3.BuildConfig;
22 import com.android.launcher3.Utilities;
23 import com.android.launcher3.uioverrides.DeviceFlag;
24 
25 import java.io.PrintWriter;
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * Defines a set of flags used to control various launcher behaviors.
31  *
32  * <p>All the flags should be defined here with appropriate default values.
33  */
34 public final class FeatureFlags {
35 
36     private static final List<DebugFlag> sDebugFlags = new ArrayList<>();
37 
38     public static final String FLAGS_PREF_NAME = "featureFlags";
39 
FeatureFlags()40     private FeatureFlags() { }
41 
showFlagTogglerUi(Context context)42     public static boolean showFlagTogglerUi(Context context) {
43         return Utilities.IS_DEBUG_DEVICE && Utilities.isDevelopersOptionsEnabled(context);
44     }
45 
46     /**
47      * True when the build has come from Android Studio and is being used for local debugging.
48      */
49     public static final boolean IS_STUDIO_BUILD = BuildConfig.DEBUG;
50 
51     /**
52      * Enable moving the QSB on the 0th screen of the workspace. This is not a configuration feature
53      * and should be modified at a project level.
54      */
55     public static final boolean QSB_ON_FIRST_SCREEN = true;
56 
57     /**
58      * Feature flag to handle define config changes dynamically instead of killing the process.
59      *
60      *
61      * To add a new flag that can be toggled through the flags UI:
62      *
63      * Declare a new ToggleableFlag below. Give it a unique key (e.g. "QSB_ON_FIRST_SCREEN"),
64      *    and set a default value for the flag. This will be the default value on Debug builds.
65      */
66     // When enabled the promise icon is visible in all apps while installation an app.
67     public static final BooleanFlag PROMISE_APPS_IN_ALL_APPS = getDebugFlag(
68             "PROMISE_APPS_IN_ALL_APPS", false, "Add promise icon in all-apps");
69 
70     // When enabled a promise icon is added to the home screen when install session is active.
71     public static final BooleanFlag PROMISE_APPS_NEW_INSTALLS = getDebugFlag(
72             "PROMISE_APPS_NEW_INSTALLS", true,
73             "Adds a promise icon to the home screen for new install sessions.");
74 
75     public static final BooleanFlag QUICKSTEP_SPRINGS = getDebugFlag(
76             "QUICKSTEP_SPRINGS", true, "Enable springs for quickstep animations");
77 
78     public static final BooleanFlag UNSTABLE_SPRINGS = getDebugFlag(
79             "UNSTABLE_SPRINGS", false, "Enable unstable springs for quickstep animations");
80 
81     public static final BooleanFlag ENABLE_LOCAL_COLOR_POPUPS = getDebugFlag(
82             "ENABLE_LOCAL_COLOR_POPUPS", false, "Enable local color extraction for popups.");
83 
84     public static final BooleanFlag KEYGUARD_ANIMATION = getDebugFlag(
85             "KEYGUARD_ANIMATION", false, "Enable animation for keyguard going away on wallpaper");
86 
87     public static final BooleanFlag ADAPTIVE_ICON_WINDOW_ANIM = getDebugFlag(
88             "ADAPTIVE_ICON_WINDOW_ANIM", true, "Use adaptive icons for window animations.");
89 
90     public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
91             "ENABLE_QUICKSTEP_LIVE_TILE", true, "Enable live tile in Quickstep overview");
92 
93     public static final BooleanFlag ENABLE_QUICKSTEP_WIDGET_APP_START = getDebugFlag(
94             "ENABLE_QUICKSTEP_WIDGET_APP_START", true,
95             "Enable Quickstep animation when launching activities from an app widget");
96 
97     // Keep as DeviceFlag to allow remote disable in emergency.
98     public static final BooleanFlag ENABLE_SUGGESTED_ACTIONS_OVERVIEW = new DeviceFlag(
99             "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", false, "Show chip hints on the overview screen");
100 
101 
102     public static final BooleanFlag ENABLE_DEVICE_SEARCH = new DeviceFlag(
103             "ENABLE_DEVICE_SEARCH", true, "Allows on device search in all apps");
104 
105     public static final BooleanFlag ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING = new DeviceFlag(
106             "ENABLE_DEVICE_SEARCH_PERFORMANCE_LOGGING", true,
107             "Allows on device search in all apps logging");
108 
109     public static final BooleanFlag IME_STICKY_SNACKBAR_EDU = getDebugFlag(
110             "IME_STICKY_SNACKBAR_EDU", true, "Show sticky IME edu in AllApps");
111 
112     public static final BooleanFlag ENABLE_PEOPLE_TILE_PREVIEW = getDebugFlag(
113             "ENABLE_PEOPLE_TILE_PREVIEW", false,
114             "Experimental: Shows conversation shortcuts on home screen as search results");
115 
116     public static final BooleanFlag FOLDER_NAME_SUGGEST = new DeviceFlag(
117             "FOLDER_NAME_SUGGEST", true,
118             "Suggests folder names instead of blank text.");
119 
120     public static final BooleanFlag FOLDER_NAME_MAJORITY_RANKING = getDebugFlag(
121             "FOLDER_NAME_MAJORITY_RANKING", true,
122             "Suggests folder names based on majority based ranking.");
123 
124     public static final BooleanFlag ENABLE_PREDICTION_DISMISS = getDebugFlag(
125             "ENABLE_PREDICTION_DISMISS", true, "Allow option to dimiss apps from predicted list");
126 
127     public static final BooleanFlag ENABLE_QUICK_CAPTURE_GESTURE = getDebugFlag(
128             "ENABLE_QUICK_CAPTURE_GESTURE", true, "Swipe from right to left to quick capture");
129 
130     public static final BooleanFlag ENABLE_QUICK_CAPTURE_WINDOW = getDebugFlag(
131             "ENABLE_QUICK_CAPTURE_WINDOW", false, "Use window to host quick capture");
132 
133     public static final BooleanFlag FORCE_LOCAL_OVERSCROLL_PLUGIN = getDebugFlag(
134             "FORCE_LOCAL_OVERSCROLL_PLUGIN", false,
135             "Use a launcher-provided OverscrollPlugin if available");
136 
137     public static final BooleanFlag ASSISTANT_GIVES_LAUNCHER_FOCUS = getDebugFlag(
138             "ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
139             "Allow Launcher to handle nav bar gestures while Assistant is running over it");
140 
141     public static final BooleanFlag HOTSEAT_MIGRATE_TO_FOLDER = getDebugFlag(
142             "HOTSEAT_MIGRATE_TO_FOLDER", false, "Should move hotseat items into a folder");
143 
144     public static final BooleanFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = getDebugFlag(
145             "ENABLE_DEEP_SHORTCUT_ICON_CACHE", true, "R/W deep shortcut in IconCache");
146 
147     public static final BooleanFlag MULTI_DB_GRID_MIRATION_ALGO = getDebugFlag(
148             "MULTI_DB_GRID_MIRATION_ALGO", true, "Use the multi-db grid migration algorithm");
149 
150     public static final BooleanFlag ENABLE_THEMED_ICONS = getDebugFlag(
151             "ENABLE_THEMED_ICONS", true, "Enable themed icons on workspace");
152 
153     // Keep as DeviceFlag for remote disable in emergency.
154     public static final BooleanFlag ENABLE_OVERVIEW_SELECTIONS = new DeviceFlag(
155             "ENABLE_OVERVIEW_SELECTIONS", true, "Show Select Mode button in Overview Actions");
156 
157     public static final BooleanFlag ENABLE_WIDGETS_PICKER_AIAI_SEARCH = new DeviceFlag(
158             "ENABLE_WIDGETS_PICKER_AIAI_SEARCH", false, "Enable AiAi search in the widgets picker");
159 
160     public static final BooleanFlag ENABLE_OVERVIEW_SHARE = getDebugFlag(
161             "ENABLE_OVERVIEW_SHARE", false, "Show Share button in Overview Actions");
162 
163     public static final BooleanFlag ENABLE_OVERVIEW_SHARING_TO_PEOPLE = getDebugFlag(
164             "ENABLE_OVERVIEW_SHARING_TO_PEOPLE", true,
165             "Show indicators for content on Overview to share with top people. ");
166 
167     public static final BooleanFlag ENABLE_OVERVIEW_CONTENT_PUSH = getDebugFlag(
168             "ENABLE_OVERVIEW_CONTENT_PUSH", false, "Show Content Push button in Overview Actions");
169 
170     public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
171             "ENABLE_DATABASE_RESTORE", false,
172             "Enable database restore when new restore session is created");
173 
174     public static final BooleanFlag ENABLE_SMARTSPACE_UNIVERSAL = getDebugFlag(
175             "ENABLE_SMARTSPACE_UNIVERSAL", false,
176             "Replace Smartspace with a version rendered by System UI.");
177 
178     public static final BooleanFlag ENABLE_SMARTSPACE_ENHANCED = getDebugFlag(
179             "ENABLE_SMARTSPACE_ENHANCED", true,
180             "Replace Smartspace with the enhanced version. "
181                     + "Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
182 
183     public static final BooleanFlag ENABLE_SMARTSPACE_FEEDBACK = getDebugFlag(
184             "ENABLE_SMARTSPACE_FEEDBACK", true,
185             "Adds a menu option to send feedback for Enhanced Smartspace.");
186 
187     public static final BooleanFlag ENABLE_SMARTSPACE_DISMISS = getDebugFlag(
188             "ENABLE_SMARTSPACE_DISMISS", true,
189             "Adds a menu option to dismiss the current Enhanced Smartspace card.");
190 
191     public static final BooleanFlag ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS =
192             getDebugFlag(
193             "ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS", false,
194             "Always use hardware optimization for folder animations.");
195 
196     public static final BooleanFlag ENABLE_ALL_APPS_EDU = getDebugFlag(
197             "ENABLE_ALL_APPS_EDU", true,
198             "Shows user a tutorial on how to get to All Apps after X amount of attempts.");
199 
200     public static final BooleanFlag SEPARATE_RECENTS_ACTIVITY = getDebugFlag(
201             "SEPARATE_RECENTS_ACTIVITY", false,
202             "Uses a separate recents activity instead of using the integrated recents+Launcher UI");
203 
204     public static final BooleanFlag ENABLE_MINIMAL_DEVICE = getDebugFlag(
205             "ENABLE_MINIMAL_DEVICE", false,
206             "Allow user to toggle minimal device mode in launcher.");
207 
208     public static final BooleanFlag EXPANDED_SMARTSPACE = new DeviceFlag(
209             "EXPANDED_SMARTSPACE", false, "Expands smartspace height to two rows. "
210               + "Any apps occupying the first row will be removed from workspace.");
211 
212     // TODO: b/172467144 Remove ENABLE_LAUNCHER_ACTIVITY_THEME_CROSSFADE feature flag.
213     public static final BooleanFlag ENABLE_LAUNCHER_ACTIVITY_THEME_CROSSFADE = new DeviceFlag(
214             "ENABLE_LAUNCHER_ACTIVITY_THEME_CROSSFADE", false, "Enables a "
215             + "crossfade animation when the system these changes.");
216 
217     // TODO: b/174174514 Remove ENABLE_APP_PREDICTIONS_WHILE_VISIBLE feature flag.
218     public static final BooleanFlag ENABLE_APP_PREDICTIONS_WHILE_VISIBLE = new DeviceFlag(
219             "ENABLE_APP_PREDICTIONS_WHILE_VISIBLE", true, "Allows app "
220             + "predictions to be updated while they are visible to the user.");
221 
222     public static final BooleanFlag ENABLE_TASKBAR = getDebugFlag(
223             "ENABLE_TASKBAR", false, "Allows a system Taskbar to be shown on larger devices.");
224 
225     public static final BooleanFlag ENABLE_OVERVIEW_GRID = getDebugFlag(
226             "ENABLE_OVERVIEW_GRID", false, "Uses grid overview layout. "
227             + "Only applicable on large screen devices.");
228 
229     public static final BooleanFlag ENABLE_TWO_PANEL_HOME = getDebugFlag(
230             "ENABLE_TWO_PANEL_HOME", false,
231             "Uses two panel on home screen. Only applicable on large screen devices.");
232 
233     public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(
234             "ENABLE_SCRIM_FOR_APP_LAUNCH", false,
235             "Enables scrim during app launch animation.");
236 
237     public static final BooleanFlag ENABLE_SPLIT_SELECT = getDebugFlag(
238             "ENABLE_SPLIT_SELECT", false, "Uses new split screen selection overview UI");
239 
240     public static final BooleanFlag ENABLE_ENFORCED_ROUNDED_CORNERS = new DeviceFlag(
241             "ENABLE_ENFORCED_ROUNDED_CORNERS", true, "Enforce rounded corners on all App Widgets");
242 
243     public static final BooleanFlag ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER = new DeviceFlag(
244             "ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER", true,
245             "Enables a local filter for recommended widgets.");
246 
247     public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag("NOTIFY_CRASHES", false,
248             "Sends a notification whenever launcher encounters an uncaught exception.");
249 
250     public static final BooleanFlag PROTOTYPE_APP_CLOSE = getDebugFlag(
251             "PROTOTYPE_APP_CLOSE", false, "Enables new app close");
252 
253     public static final BooleanFlag ENABLE_WALLPAPER_SCRIM = getDebugFlag(
254             "ENABLE_WALLPAPER_SCRIM", false,
255             "Enables scrim over wallpaper for text protection.");
256 
initialize(Context context)257     public static void initialize(Context context) {
258         synchronized (sDebugFlags) {
259             for (DebugFlag flag : sDebugFlags) {
260                 flag.initialize(context);
261             }
262             sDebugFlags.sort((f1, f2) -> f1.key.compareToIgnoreCase(f2.key));
263         }
264     }
265 
getDebugFlags()266     static List<DebugFlag> getDebugFlags() {
267         synchronized (sDebugFlags) {
268             return new ArrayList<>(sDebugFlags);
269         }
270     }
271 
dump(PrintWriter pw)272     public static void dump(PrintWriter pw) {
273         pw.println("DeviceFlags:");
274         synchronized (sDebugFlags) {
275             for (DebugFlag flag : sDebugFlags) {
276                 if (flag instanceof DeviceFlag) {
277                     pw.println("  " + flag.toString());
278                 }
279             }
280         }
281         pw.println("DebugFlags:");
282         synchronized (sDebugFlags) {
283             for (DebugFlag flag : sDebugFlags) {
284                 if (!(flag instanceof DeviceFlag)) {
285                     pw.println("  " + flag.toString());
286                 }
287             }
288         }
289     }
290 
291     public static class BooleanFlag {
292 
293         public final String key;
294         public boolean defaultValue;
295 
BooleanFlag(String key, boolean defaultValue)296         public BooleanFlag(String key, boolean defaultValue) {
297             this.key = key;
298             this.defaultValue = defaultValue;
299         }
300 
get()301         public boolean get() {
302             return defaultValue;
303         }
304 
305         @Override
toString()306         public String toString() {
307             return appendProps(new StringBuilder()).toString();
308         }
309 
appendProps(StringBuilder src)310         protected StringBuilder appendProps(StringBuilder src) {
311             return src.append(key).append(", defaultValue=").append(defaultValue);
312         }
313 
addChangeListener(Context context, Runnable r)314         public void addChangeListener(Context context, Runnable r) { }
315 
removeChangeListener(Runnable r)316         public void removeChangeListener(Runnable r) {}
317     }
318 
319     public static class DebugFlag extends BooleanFlag {
320 
321         public final String description;
322         private boolean mCurrentValue;
323 
DebugFlag(String key, boolean defaultValue, String description)324         public DebugFlag(String key, boolean defaultValue, String description) {
325             super(key, defaultValue);
326             this.description = description;
327             mCurrentValue = this.defaultValue;
328             synchronized (sDebugFlags) {
329                 sDebugFlags.add(this);
330             }
331         }
332 
333         @Override
get()334         public boolean get() {
335             return mCurrentValue;
336         }
337 
initialize(Context context)338         public void initialize(Context context) {
339             mCurrentValue = context.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
340                     .getBoolean(key, defaultValue);
341         }
342 
343         @Override
appendProps(StringBuilder src)344         protected StringBuilder appendProps(StringBuilder src) {
345             return super.appendProps(src).append(", mCurrentValue=").append(mCurrentValue);
346         }
347     }
348 
getDebugFlag(String key, boolean defaultValue, String description)349     private static BooleanFlag getDebugFlag(String key, boolean defaultValue, String description) {
350         return Utilities.IS_DEBUG_DEVICE
351                 ? new DebugFlag(key, defaultValue, description)
352                 : new BooleanFlag(key, defaultValue);
353     }
354 }
355