1 /* 2 * Copyright (C) 2008 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; 18 19 import static android.util.Base64.NO_PADDING; 20 import static android.util.Base64.NO_WRAP; 21 22 import static com.android.launcher3.icons.cache.CacheLookupFlag.DEFAULT_LOOKUP_FLAG; 23 24 import android.database.sqlite.SQLiteDatabase; 25 import android.provider.BaseColumns; 26 import android.util.Base64; 27 28 import androidx.annotation.NonNull; 29 30 import com.android.launcher3.icons.cache.CacheLookupFlag; 31 import com.android.launcher3.model.data.ItemInfo; 32 33 import java.util.LinkedHashMap; 34 import java.util.stream.Collectors; 35 36 /** 37 * Settings related utilities. 38 */ 39 public class LauncherSettings { 40 41 /** 42 * Types of animations. 43 */ 44 public static final class Animation { 45 /** 46 * The default animation for a given view/item info type. 47 */ 48 public static final int DEFAULT = 0; 49 /** 50 * An animation using the view's background. 51 */ 52 public static final int VIEW_BACKGROUND = 1; 53 /** 54 * The default animation for a given view/item info type, but without the splash icon. 55 */ 56 public static final int DEFAULT_NO_ICON = 2; 57 } 58 59 /** 60 * Favorites. 61 */ 62 public static final class Favorites implements BaseColumns { 63 /** 64 * The time of the last update to this row. 65 * <P>Type: INTEGER</P> 66 */ 67 public static final String MODIFIED = "modified"; 68 69 /** 70 * Descriptive name of the gesture that can be displayed to the user. 71 * <P>Type: TEXT</P> 72 */ 73 public static final String TITLE = "title"; 74 75 /** 76 * The Intent URL of the gesture, describing what it points to. This 77 * value is given to {@link android.content.Intent#parseUri(String, int)} to create 78 * an Intent that can be launched. 79 * <P>Type: TEXT</P> 80 */ 81 public static final String INTENT = "intent"; 82 83 /** 84 * The type of the gesture 85 * 86 * <P>Type: INTEGER</P> 87 */ 88 public static final String ITEM_TYPE = "itemType"; 89 90 /** 91 * The gesture is a package 92 */ 93 public static final int ITEM_TYPE_NON_ACTIONABLE = -1; 94 /** 95 * The gesture is an application 96 */ 97 public static final int ITEM_TYPE_APPLICATION = 0; 98 99 /** 100 * The gesture is an application created shortcut 101 * @deprecated This is no longer supported. Use {@link #ITEM_TYPE_DEEP_SHORTCUT} instead 102 */ 103 @Deprecated 104 public static final int ITEM_TYPE_SHORTCUT = 1; 105 106 /** 107 * The favorite is a user created folder 108 */ 109 public static final int ITEM_TYPE_FOLDER = 2; 110 111 /** 112 * The favorite is a widget 113 */ 114 public static final int ITEM_TYPE_APPWIDGET = 4; 115 116 /** 117 * The favorite is a custom widget provided by the launcher 118 */ 119 public static final int ITEM_TYPE_CUSTOM_APPWIDGET = 5; 120 121 /** 122 * The gesture is an application created deep shortcut 123 */ 124 public static final int ITEM_TYPE_DEEP_SHORTCUT = 6; 125 126 /** 127 * The favorite is an app pair for launching split screen 128 */ 129 public static final int ITEM_TYPE_APP_PAIR = 10; 130 131 // *** Below enum values are used for metrics purpose but not used in Favorites DB *** 132 133 /** 134 * Type of the item is recents task. 135 */ 136 public static final int ITEM_TYPE_TASK = 7; 137 138 /** 139 * The item is QSB 140 */ 141 public static final int ITEM_TYPE_QSB = 8; 142 143 /** 144 * The favorite is a search action 145 */ 146 public static final int ITEM_TYPE_SEARCH_ACTION = 9; 147 148 /** 149 * Private space install app button. 150 */ 151 public static final int ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON = 11; 152 153 /** 154 * The custom icon bitmap. 155 * <P>Type: BLOB</P> 156 */ 157 public static final String ICON = "icon"; 158 159 public static final String TABLE_NAME = "favorites"; 160 161 /** 162 * Backup table created when user hotseat is moved to workspace for hybrid hotseat 163 */ 164 public static final String HYBRID_HOTSEAT_BACKUP_TABLE = "hotseat_restore_backup"; 165 166 /** 167 * Temporary table used specifically for multi-db grid migrations 168 */ 169 public static final String TMP_TABLE = "favorites_tmp"; 170 171 /** 172 * The container holding the favorite 173 * <P>Type: INTEGER</P> 174 */ 175 public static final String CONTAINER = "container"; 176 177 /** 178 * The icon is a resource identified by a package name and an integer id. 179 */ 180 public static final int CONTAINER_DESKTOP = -100; 181 public static final int CONTAINER_HOTSEAT = -101; 182 public static final int CONTAINER_PREDICTION = -102; 183 public static final int CONTAINER_WIDGETS_PREDICTION = -111; 184 public static final int CONTAINER_HOTSEAT_PREDICTION = -103; 185 public static final int CONTAINER_ALL_APPS = -104; 186 public static final int CONTAINER_WIDGETS_TRAY = -105; 187 public static final int CONTAINER_BOTTOM_WIDGETS_TRAY = -112; 188 public static final int CONTAINER_PIN_WIDGETS = -113; 189 public static final int CONTAINER_WALLPAPERS = -114; 190 public static final int CONTAINER_SHORTCUTS = -107; 191 public static final int CONTAINER_SETTINGS = -108; 192 public static final int CONTAINER_TASKSWITCHER = -109; 193 public static final int CONTAINER_PRIVATESPACE = -110; 194 195 // Represents any of the extended containers implemented in non-AOSP variants. 196 public static final int EXTENDED_CONTAINERS = -200; 197 198 public static final int CONTAINER_UNKNOWN = -1; 199 containerToString(int container)200 public static final String containerToString(int container) { 201 switch (container) { 202 case CONTAINER_DESKTOP: return "desktop"; 203 case CONTAINER_HOTSEAT: return "hotseat"; 204 case CONTAINER_PREDICTION: return "prediction"; 205 case CONTAINER_ALL_APPS: return "all_apps"; 206 case CONTAINER_WIDGETS_TRAY: return "widgets_tray"; 207 case CONTAINER_SHORTCUTS: return "shortcuts"; 208 default: return String.valueOf(container); 209 } 210 } 211 itemTypeToString(int type)212 public static final String itemTypeToString(int type) { 213 switch(type) { 214 case ITEM_TYPE_APPLICATION: return "APP"; 215 case ITEM_TYPE_FOLDER: return "FOLDER"; 216 case ITEM_TYPE_APPWIDGET: return "WIDGET"; 217 case ITEM_TYPE_CUSTOM_APPWIDGET: return "CUSTOMWIDGET"; 218 case ITEM_TYPE_DEEP_SHORTCUT: return "DEEPSHORTCUT"; 219 case ITEM_TYPE_TASK: return "TASK"; 220 case ITEM_TYPE_QSB: return "QSB"; 221 case ITEM_TYPE_APP_PAIR: return "APP_PAIR"; 222 case ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON: 223 return "PRIVATE_SPACE_INSTALL_APP_BUTTON"; 224 default: return String.valueOf(type); 225 } 226 } 227 228 /** 229 * The screen holding the favorite (if container is CONTAINER_DESKTOP) 230 * <P>Type: INTEGER</P> 231 */ 232 public static final String SCREEN = "screen"; 233 234 /** 235 * The X coordinate of the cell holding the favorite 236 * (if container is CONTAINER_HOTSEAT or CONTAINER_HOTSEAT) 237 * <P>Type: INTEGER</P> 238 */ 239 public static final String CELLX = "cellX"; 240 241 /** 242 * The Y coordinate of the cell holding the favorite 243 * (if container is CONTAINER_DESKTOP) 244 * <P>Type: INTEGER</P> 245 */ 246 public static final String CELLY = "cellY"; 247 248 /** 249 * The X span of the cell holding the favorite 250 * <P>Type: INTEGER</P> 251 */ 252 public static final String SPANX = "spanX"; 253 254 /** 255 * The Y span of the cell holding the favorite 256 * <P>Type: INTEGER</P> 257 */ 258 public static final String SPANY = "spanY"; 259 260 /** 261 * The profile id of the item in the cell. 262 * <P> 263 * Type: INTEGER 264 * </P> 265 */ 266 public static final String PROFILE_ID = "profileId"; 267 268 /** 269 * The appWidgetId of the widget 270 * 271 * <P>Type: INTEGER</P> 272 */ 273 public static final String APPWIDGET_ID = "appWidgetId"; 274 275 /** 276 * The ComponentName of the widget provider 277 * 278 * <P>Type: STRING</P> 279 */ 280 public static final String APPWIDGET_PROVIDER = "appWidgetProvider"; 281 282 /** 283 * Boolean indicating that his item was restored and not yet successfully bound. 284 * <P>Type: INTEGER</P> 285 */ 286 public static final String RESTORED = "restored"; 287 288 /** 289 * Indicates the position of the item inside an auto-arranged view like folder or hotseat. 290 * <p>Type: INTEGER</p> 291 */ 292 public static final String RANK = "rank"; 293 294 /** 295 * Stores general flag based options for {@link ItemInfo}s. 296 * <p>Type: INTEGER</p> 297 */ 298 public static final String OPTIONS = "options"; 299 300 /** 301 * Stores the source container that the widget was added from. 302 * <p>Type: INTEGER</p> 303 */ 304 public static final String APPWIDGET_SOURCE = "appWidgetSource"; 305 addTableToDb(SQLiteDatabase db, long myProfileId, boolean optional)306 public static void addTableToDb(SQLiteDatabase db, long myProfileId, boolean optional) { 307 addTableToDb(db, myProfileId, optional, TABLE_NAME); 308 } 309 addTableToDb(SQLiteDatabase db, long myProfileId, boolean optional, String tableName)310 public static void addTableToDb(SQLiteDatabase db, long myProfileId, boolean optional, 311 String tableName) { 312 db.execSQL("CREATE TABLE " + (optional ? " IF NOT EXISTS " : "") + tableName + " (" 313 + getJoinedColumnsToTypes(myProfileId) + ");"); 314 } 315 316 // LinkedHashMap maintains Order of Insertion 317 @NonNull getColumnsToTypes(long profileId)318 private static LinkedHashMap<String, String> getColumnsToTypes(long profileId) { 319 final LinkedHashMap<String, String> columnsToTypes = new LinkedHashMap<>(); 320 columnsToTypes.put(_ID, "INTEGER PRIMARY KEY"); 321 columnsToTypes.put(TITLE, "TEXT"); 322 columnsToTypes.put(INTENT, "TEXT"); 323 columnsToTypes.put(CONTAINER, "INTEGER"); 324 columnsToTypes.put(SCREEN, "INTEGER"); 325 columnsToTypes.put(CELLX, "INTEGER"); 326 columnsToTypes.put(CELLY, "INTEGER"); 327 columnsToTypes.put(SPANX, "INTEGER"); 328 columnsToTypes.put(SPANY, "INTEGER"); 329 columnsToTypes.put(ITEM_TYPE, "INTEGER"); 330 columnsToTypes.put(APPWIDGET_ID, "INTEGER NOT NULL DEFAULT -1"); 331 columnsToTypes.put(ICON, "BLOB"); 332 columnsToTypes.put(APPWIDGET_PROVIDER, "TEXT"); 333 columnsToTypes.put(MODIFIED, "INTEGER NOT NULL DEFAULT 0"); 334 columnsToTypes.put(RESTORED, "INTEGER NOT NULL DEFAULT 0"); 335 columnsToTypes.put(PROFILE_ID, "INTEGER DEFAULT " + profileId); 336 columnsToTypes.put(RANK, "INTEGER NOT NULL DEFAULT 0"); 337 columnsToTypes.put(OPTIONS, "INTEGER NOT NULL DEFAULT 0"); 338 columnsToTypes.put(APPWIDGET_SOURCE, "INTEGER NOT NULL DEFAULT -1"); 339 return columnsToTypes; 340 } 341 getJoinedColumnsToTypes(long profileId)342 private static String getJoinedColumnsToTypes(long profileId) { 343 return getColumnsToTypes(profileId) 344 .entrySet() 345 .stream() 346 .map(it -> it.getKey() + " " + it.getValue()) 347 .collect(Collectors.joining(", ")); 348 } 349 350 /** 351 * Returns an ordered list of columns in the Favorites table as one string, ready to use in 352 * an SQL statement. 353 */ 354 @NonNull getColumns(long profileId)355 public static String getColumns(long profileId) { 356 return String.join(", ", getColumnsToTypes(profileId).keySet()); 357 } 358 359 /** 360 * Lookup flag to be used for items which are visible on the home screen 361 */ 362 public static final CacheLookupFlag DESKTOP_ICON_FLAG = DEFAULT_LOOKUP_FLAG; 363 } 364 365 /** 366 * Launcher settings 367 */ 368 public static final class Settings { 369 public static final String LAYOUT_PROVIDER_KEY = "launcher3.layout.provider"; 370 public static final String LAYOUT_DIGEST_LABEL = "launcher-layout"; 371 public static final String LAYOUT_DIGEST_TAG = "ignore"; 372 public static final String BLOB_KEY_PREFIX = "blob://"; 373 374 /** 375 * Creates a key to be used for {@link #LAYOUT_PROVIDER_KEY} 376 * @param digest byte[] representing the message digest for the blob handle 377 */ createBlobProviderKey(byte[] digest)378 public static String createBlobProviderKey(byte[] digest) { 379 return BLOB_KEY_PREFIX + Base64.encodeToString(digest, NO_WRAP | NO_PADDING); 380 } 381 } 382 } 383