From 7315bdd23669d54bdfdb56beda14eeb3425943da Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Mon, 3 Feb 2020 18:56:54 -0800 Subject: [PATCH 01/51] Change unnamed folder hint and style Bug: 135182686 Test: Manual Change-Id: Ic63d89fdbd5d8ab9b0d215e916f3d2f038760547 --- res/layout/user_folder_icon_normalized.xml | 4 ++-- res/values/attrs.xml | 1 + res/values/strings.xml | 2 +- res/values/styles.xml | 2 ++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml index 893d79654f..923352e707 100644 --- a/res/layout/user_folder_icon_normalized.xml +++ b/res/layout/user_folder_icon_normalized.xml @@ -46,9 +46,9 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" + style="@style/TextHeadline" android:layout_weight="1" android:background="@android:color/transparent" - android:fontFamily="sans-serif-condensed" android:textStyle="bold" android:gravity="center_horizontal" android:hint="@string/folder_hint_text" @@ -58,7 +58,7 @@ android:singleLine="true" android:textColor="?attr/folderTextColor" android:textColorHighlight="?android:attr/colorControlHighlight" - android:textColorHint="?attr/folderTextColor" + android:textColorHint="?attr/folderHintColor" android:textSize="@dimen/folder_label_text_size" /> + diff --git a/res/values/strings.xml b/res/values/strings.xml index bfa92f7537..bde3c3127e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -142,7 +142,7 @@ This is a system app and can\'t be uninstalled. - Unnamed Folder + Tap to edit diff --git a/res/values/styles.xml b/res/values/styles.xml index 35ae49c8ee..1174a2fdaa 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -48,6 +48,7 @@ #CDFFFFFF ?android:attr/colorPrimary #FF212121 + #FF616161 #CCFFFFFF false @@ -96,6 +97,7 @@ #DD3C4043 #FF80868B @android:color/white + #FFCCCCCC true #99FFFFFF From ae701bfcc46350976610efb31f84ec08781533fc Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 4 Feb 2020 12:06:18 -0800 Subject: [PATCH 02/51] Investigator: adding "Screen is empty" as another sign of crashed sysui Also generating recognizable anomaly message in more cases Change-Id: Ia4d4d87a1a46291f3ea1057e00acbd98d9ccb3a5 --- .../com/android/launcher3/util/rule/FailureInvestigator.java | 2 +- .../com/android/launcher3/tapl/LauncherInstrumentation.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java b/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java index d6dfdd98f8..644550118c 100644 --- a/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java +++ b/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java @@ -55,7 +55,7 @@ class FailureInvestigator { private static final ExceptionMatch[] EXCEPTION_MATCHES = { new ExceptionMatch( "java.lang.AssertionError: http://go/tapl : Tests are broken by a " - + "non-Launcher system error: Phone is locked", + + "non-Launcher system error: (Phone is locked|Screen is empty)", new LogcatMatch[]{ new LogcatMatch( "BroadcastQueue: Can't deliver broadcast to com.android" diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index cf5b24ed75..15a6d36137 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -340,7 +340,8 @@ public final class LauncherInstrumentation { public void checkForAnomaly() { final String anomalyMessage = getAnomalyMessage(); if (anomalyMessage != null) { - String message = "Tests are broken by a non-Launcher system error: " + anomalyMessage; + String message = "http://go/tapl : Tests are broken by a non-Launcher system error: " + + anomalyMessage; log("Hierarchy dump for: " + message); dumpViewHierarchy(); From b8a54f967b69fe60261d8ce808f8342ccc36ba2a Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 4 Feb 2020 18:13:52 -0800 Subject: [PATCH 03/51] Adding one more automatic flake classifier Change-Id: I5ab68c3d02a5e82081485b0845b0e7c24280aa1c --- .../com/android/launcher3/util/rule/FailureInvestigator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java b/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java index d6dfdd98f8..695b36c3d8 100644 --- a/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java +++ b/tests/src/com/android/launcher3/util/rule/FailureInvestigator.java @@ -87,6 +87,11 @@ class FailureInvestigator { return 145935261; } + if (matches("java\\.lang\\.AssertionError\\: http\\:\\/\\/go\\/tapl \\: want to get " + + "workspace object; Presence of recents button doesn't match the interaction " + + "mode, mode\\=ZERO_BUTTON, hasRecents\\=true", exception)) { + return 148422894; + } final String logSinceBoot; try { From 7df93d28d43170620f824d0421e7a373b0f5c352 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Mon, 27 Jan 2020 13:44:06 -0800 Subject: [PATCH 04/51] Setup infrastructure (multi-db support) for the new grid migration algorithm We'll have a db for each grid option and a db for back up / restore. TODO(pinyaoting): support back up / restore using the new infrastructure, particularly calls to GridBackupTable should use different DBs when the feature flag (NEW_GRID_MIGRATION_ALGORITHM) is on. Bug: 144052802 Test: N/A Change-Id: I644a3e70148bd78204a747a337446a3c038f616f --- res/values/attrs.xml | 1 + res/xml/device_profiles.xml | 3 + .../launcher3/model/BackupRestoreTest.java | 2 +- .../launcher3/model/GridBackupTableTest.java | 12 ++-- .../launcher3/InvariantDeviceProfile.java | 5 ++ src/com/android/launcher3/LauncherFiles.java | 11 ++- .../android/launcher3/LauncherProvider.java | 67 +++++++++++++++---- .../android/launcher3/LauncherSettings.java | 2 + .../launcher3/config/FeatureFlags.java | 3 + .../launcher3/model/GridBackupTable.java | 47 ++++++++----- .../model/GridSizeMigrationTask.java | 2 +- .../model/GridSizeMigrationTaskV2.java | 40 +++++++++++ .../android/launcher3/model/LoaderTask.java | 5 +- .../launcher3/provider/RestoreDbTask.java | 6 +- 14 files changed, 164 insertions(+), 42 deletions(-) create mode 100644 src/com/android/launcher3/model/GridSizeMigrationTaskV2.java diff --git a/res/values/attrs.xml b/res/values/attrs.xml index de17eb7b4f..707424c9f1 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -115,6 +115,7 @@ + diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml index 82547d5217..1c99dfcfa7 100644 --- a/res/xml/device_profiles.xml +++ b/res/xml/device_profiles.xml @@ -24,6 +24,7 @@ launcher:numFolderRows="2" launcher:numFolderColumns="3" launcher:numHotseatIcons="3" + launcher:dbFile="launcher_3_by_3.db" launcher:defaultLayoutId="@xml/default_workspace_3x3" > ALL_FILES = Collections.unmodifiableList(Arrays.asList( LAUNCHER_DB, + LAUNCHER_4_BY_4_DB, + LAUNCHER_3_BY_3_DB, + LAUNCHER_2_BY_2_DB, + BACKUP_DB, SHARED_PREFERENCES_KEY + XML, WIDGET_PREVIEWS_DB, MANAGED_USER_PREFERENCES_KEY + XML, diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index b0ab35c5b0..5544240f57 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO; import static com.android.launcher3.provider.LauncherDbUtils.dropTable; import static com.android.launcher3.provider.LauncherDbUtils.tableExists; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; @@ -157,6 +158,17 @@ public class LauncherProvider extends ContentProvider { } } + private synchronized boolean updateCurrentOpenHelper() { + final InvariantDeviceProfile idp = InvariantDeviceProfile.INSTANCE.get(getContext()); + if (TextUtils.equals(idp.dbFile, mOpenHelper.getDatabaseName())) { + return false; + } + + mOpenHelper.close(); + mOpenHelper = new DatabaseHelper(getContext()); + return true; + } + @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { @@ -210,7 +222,7 @@ public class LauncherProvider extends ContentProvider { addModifiedTime(initialValues); final int rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues); if (rowId < 0) return null; - mOpenHelper.onAddOrDeleteOp(db); + onAddOrDeleteOp(db); uri = ContentUris.withAppendedId(uri, rowId); reloadLauncherIfExternal(); @@ -268,7 +280,7 @@ public class LauncherProvider extends ContentProvider { return 0; } } - mOpenHelper.onAddOrDeleteOp(db); + onAddOrDeleteOp(db); t.commit(); } @@ -294,7 +306,7 @@ public class LauncherProvider extends ContentProvider { results[i].count != null && results[i].count > 0; } if (isAddOrDelete) { - mOpenHelper.onAddOrDeleteOp(t.getDb()); + onAddOrDeleteOp(t.getDb()); } t.commit(); @@ -316,7 +328,7 @@ public class LauncherProvider extends ContentProvider { } int count = db.delete(args.table, args.where, args.args); if (count > 0) { - mOpenHelper.onAddOrDeleteOp(db); + onAddOrDeleteOp(db); reloadLauncherIfExternal(); } return count; @@ -360,12 +372,14 @@ public class LauncherProvider extends ContentProvider { } case LauncherSettings.Settings.METHOD_NEW_ITEM_ID: { Bundle result = new Bundle(); - result.putInt(LauncherSettings.Settings.EXTRA_VALUE, mOpenHelper.generateNewItemId()); + result.putInt(LauncherSettings.Settings.EXTRA_VALUE, + mOpenHelper.generateNewItemId()); return result; } case LauncherSettings.Settings.METHOD_NEW_SCREEN_ID: { Bundle result = new Bundle(); - result.putInt(LauncherSettings.Settings.EXTRA_VALUE, mOpenHelper.generateNewScreenId()); + result.putInt(LauncherSettings.Settings.EXTRA_VALUE, + mOpenHelper.generateNewScreenId()); return result; } case LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB: { @@ -387,8 +401,12 @@ public class LauncherProvider extends ContentProvider { return result; } case LauncherSettings.Settings.METHOD_REFRESH_BACKUP_TABLE: { - mOpenHelper.mBackupTableExists = - tableExists(mOpenHelper.getReadableDatabase(), Favorites.BACKUP_TABLE_NAME); + // TODO(pinyaoting): Update the behavior here. + if (!MULTI_DB_GRID_MIRATION_ALGO.get()) { + mOpenHelper.mBackupTableExists = + tableExists(mOpenHelper.getReadableDatabase(), + Favorites.BACKUP_TABLE_NAME); + } return null; } case LauncherSettings.Settings.METHOD_RESTORE_BACKUP_TABLE: { @@ -399,10 +417,26 @@ public class LauncherProvider extends ContentProvider { TOKEN_RESTORE_BACKUP_TABLE, RESTORE_BACKUP_TABLE_DELAY); return null; } + case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: { + if (MULTI_DB_GRID_MIRATION_ALGO.get()) { + Bundle result = new Bundle(); + result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE, + updateCurrentOpenHelper()); + return result; + } + } } return null; } + private void onAddOrDeleteOp(SQLiteDatabase db) { + if (MULTI_DB_GRID_MIRATION_ALGO.get()) { + // TODO(pingyaoting): Implement the behavior here. + } else { + mOpenHelper.onAddOrDeleteOp(db); + } + } + /** * Deletes any empty folder from the DB. * @return Ids of deleted folders. @@ -551,14 +585,16 @@ public class LauncherProvider extends ContentProvider { /** * The class is subclassed in tests to create an in-memory db. */ - public static class DatabaseHelper extends NoLocaleSQLiteHelper implements LayoutParserCallback { + public static class DatabaseHelper extends NoLocaleSQLiteHelper implements + LayoutParserCallback { private final Context mContext; private int mMaxItemId = -1; private int mMaxScreenId = -1; private boolean mBackupTableExists; DatabaseHelper(Context context) { - this(context, LauncherFiles.LAUNCHER_DB); + this(context, MULTI_DB_GRID_MIRATION_ALGO.get() ? InvariantDeviceProfile.INSTANCE.get( + context).dbFile : LauncherFiles.LAUNCHER_DB); // Table creation sometimes fails silently, which leads to a crash loop. // This way, we will try to create a table every time after crash, so the device // would eventually be able to recover. @@ -567,7 +603,10 @@ public class LauncherProvider extends ContentProvider { // This operation is a no-op if the table already exists. addFavoritesTable(getWritableDatabase(), true); } - mBackupTableExists = tableExists(getReadableDatabase(), Favorites.BACKUP_TABLE_NAME); + if (!MULTI_DB_GRID_MIRATION_ALGO.get()) { + mBackupTableExists = tableExists(getReadableDatabase(), + Favorites.BACKUP_TABLE_NAME); + } initIds(); } @@ -575,8 +614,8 @@ public class LauncherProvider extends ContentProvider { /** * Constructor used in tests and for restore. */ - public DatabaseHelper(Context context, String tableName) { - super(context, tableName, SCHEMA_VERSION); + public DatabaseHelper(Context context, String dbName) { + super(context, dbName, SCHEMA_VERSION); mContext = context; } @@ -606,7 +645,7 @@ public class LauncherProvider extends ContentProvider { } protected void onAddOrDeleteOp(SQLiteDatabase db) { - if (mBackupTableExists) { + if (!MULTI_DB_GRID_MIRATION_ALGO.get() && mBackupTableExists) { dropTable(db, Favorites.BACKUP_TABLE_NAME); mBackupTableExists = false; } diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index 4c5c61cbc8..49831f6495 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -302,6 +302,8 @@ public class LauncherSettings { public static final String METHOD_RESTORE_BACKUP_TABLE = "restore_backup_table"; + public static final String METHOD_UPDATE_CURRENT_OPEN_HELPER = "update_current_open_helper"; + public static final String EXTRA_VALUE = "value"; public static Bundle call(ContentResolver cr, String method) { diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index b1a2c3368d..cc33965ba4 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -112,6 +112,9 @@ public final class FeatureFlags { public static final BooleanFlag ENABLE_DEEP_SHORTCUT_ICON_CACHE = getDebugFlag( "ENABLE_DEEP_SHORTCUT_ICON_CACHE", true, "R/W deep shortcut in IconCache"); + public static final BooleanFlag MULTI_DB_GRID_MIRATION_ALGO = getDebugFlag( + "MULTI_DB_GRID_MIRATION_ALGO", false, "Use the multi-db grid migration algorithm"); + public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag( "ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", false, "Show launcher preview in grid picker"); diff --git a/src/com/android/launcher3/model/GridBackupTable.java b/src/com/android/launcher3/model/GridBackupTable.java index fc9948ed84..eb99af54b7 100644 --- a/src/com/android/launcher3/model/GridBackupTable.java +++ b/src/com/android/launcher3/model/GridBackupTable.java @@ -33,6 +33,8 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherSettings.Settings; import com.android.launcher3.pm.UserCache; +import java.util.Objects; + /** * Helper class to backup and restore Favorites table into a separate table * within the same data base. @@ -61,7 +63,8 @@ public class GridBackupTable { private static final int STATE_SANITIZED = 2; private final Context mContext; - private final SQLiteDatabase mDb; + private final SQLiteDatabase mFavoritesDb; + private final SQLiteDatabase mBackupDb; private final int mOldHotseatSize; private final int mOldGridX; @@ -74,10 +77,11 @@ public class GridBackupTable { @IntDef({STATE_NOT_FOUND, STATE_RAW, STATE_SANITIZED}) private @interface BackupState { } - public GridBackupTable(Context context, SQLiteDatabase db, + public GridBackupTable(Context context, SQLiteDatabase favoritesDb, SQLiteDatabase backupDb, int hotseatSize, int gridX, int gridY) { mContext = context; - mDb = db; + mFavoritesDb = favoritesDb; + mBackupDb = backupDb; mOldHotseatSize = hotseatSize; mOldGridX = gridX; @@ -90,7 +94,7 @@ public class GridBackupTable { */ public boolean backupOrRestoreAsNeeded() { // Check if backup table exists - if (!tableExists(mDb, BACKUP_TABLE_NAME)) { + if (!tableExists(mBackupDb, BACKUP_TABLE_NAME)) { if (Settings.call(mContext.getContentResolver(), Settings.METHOD_WAS_EMPTY_DB_CREATED) .getBoolean(Settings.EXTRA_VALUE, false)) { // No need to copy if empty DB was created. @@ -105,7 +109,7 @@ public class GridBackupTable { } long userSerial = UserCache.INSTANCE.get(mContext).getSerialNumberForUser( Process.myUserHandle()); - copyTable(BACKUP_TABLE_NAME, Favorites.TABLE_NAME, userSerial); + copyTable(mBackupDb, BACKUP_TABLE_NAME, mFavoritesDb, Favorites.TABLE_NAME, userSerial); Log.d(TAG, "Backup table found"); return true; } @@ -118,28 +122,37 @@ public class GridBackupTable { /** * Copy valid grid entries from one table to another. */ - private void copyTable(String from, String to, long userSerial) { - dropTable(mDb, to); - Favorites.addTableToDb(mDb, userSerial, false, to); - mDb.execSQL("INSERT INTO " + to + " SELECT * FROM " + from + " where _id > " + ID_PROPERTY); + private static void copyTable(SQLiteDatabase fromDb, String fromTable, SQLiteDatabase toDb, + String toTable, long userSerial) { + dropTable(toDb, toTable); + Favorites.addTableToDb(toDb, userSerial, false, toTable); + if (fromDb != toDb) { + toDb.execSQL("ATTACH DATABASE '" + fromDb.getPath() + "' AS from_db"); + toDb.execSQL( + "INSERT INTO " + toTable + " SELECT * FROM from_db." + fromTable + + " where _id > " + ID_PROPERTY); + } else { + toDb.execSQL("INSERT INTO " + toTable + " SELECT * FROM " + fromTable + " where _id > " + + ID_PROPERTY); + } } private void encodeDBProperties(int options) { ContentValues values = new ContentValues(); values.put(Favorites._ID, ID_PROPERTY); - values.put(KEY_DB_VERSION, mDb.getVersion()); + values.put(KEY_DB_VERSION, mFavoritesDb.getVersion()); values.put(KEY_GRID_X_SIZE, mOldGridX); values.put(KEY_GRID_Y_SIZE, mOldGridY); values.put(KEY_HOTSEAT_SIZE, mOldHotseatSize); values.put(Favorites.OPTIONS, options); - mDb.insert(BACKUP_TABLE_NAME, null, values); + mBackupDb.insert(BACKUP_TABLE_NAME, null, values); } /** * Load DB properties from grid backup table. */ public @BackupState int loadDBProperties() { - try (Cursor c = mDb.query(BACKUP_TABLE_NAME, new String[] { + try (Cursor c = mBackupDb.query(BACKUP_TABLE_NAME, new String[] { KEY_DB_VERSION, // 0 KEY_GRID_X_SIZE, // 1 KEY_GRID_Y_SIZE, // 2 @@ -150,7 +163,7 @@ public class GridBackupTable { Log.e(TAG, "Meta data not found in backup table"); return STATE_NOT_FOUND; } - if (!validateDBVersion(mDb.getVersion(), c.getInt(0))) { + if (!validateDBVersion(mBackupDb.getVersion(), c.getInt(0))) { return STATE_NOT_FOUND; } @@ -166,7 +179,7 @@ public class GridBackupTable { * Restore workspace from raw backup if available. */ public boolean restoreFromRawBackupIfAvailable(long oldProfileId) { - if (!tableExists(mDb, Favorites.BACKUP_TABLE_NAME) + if (!tableExists(mBackupDb, Favorites.BACKUP_TABLE_NAME) || loadDBProperties() != STATE_RAW || mOldHotseatSize != mRestoredHotseatSize || mOldGridX != mRestoredGridX @@ -174,7 +187,8 @@ public class GridBackupTable { // skip restore if dimensions in backup table differs from current setup. return false; } - copyTable(Favorites.BACKUP_TABLE_NAME, Favorites.TABLE_NAME, oldProfileId); + copyTable(mBackupDb, Favorites.BACKUP_TABLE_NAME, mFavoritesDb, Favorites.TABLE_NAME, + oldProfileId); Log.d(TAG, "Backup restored"); return true; } @@ -183,7 +197,8 @@ public class GridBackupTable { * Performs a backup on the workspace layout. */ public void doBackup(long profileId, int options) { - copyTable(Favorites.TABLE_NAME, Favorites.BACKUP_TABLE_NAME, profileId); + copyTable(mFavoritesDb, Favorites.TABLE_NAME, mBackupDb, Favorites.BACKUP_TABLE_NAME, + profileId); encodeDBProperties(options); } diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java index c35c4b9076..4f9206629a 100644 --- a/src/com/android/launcher3/model/GridSizeMigrationTask.java +++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java @@ -909,7 +909,7 @@ public class GridSizeMigrationTask { boolean dbChanged = false; GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(), - srcHotseatCount, sourceSize.x, sourceSize.y); + transaction.getDb(), srcHotseatCount, sourceSize.x, sourceSize.y); if (backupTable.backupOrRestoreAsNeeded()) { dbChanged = true; srcHotseatCount = backupTable.getRestoreHotseatAndGridSize(sourceSize); diff --git a/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java new file mode 100644 index 0000000000..63b7191a92 --- /dev/null +++ b/src/com/android/launcher3/model/GridSizeMigrationTaskV2.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.model; + +import android.content.Context; + +/** + * This class takes care of shrinking the workspace (by maximum of one row and one column), as a + * result of restoring from a larger device or device density change. + */ +public class GridSizeMigrationTaskV2 { + + private GridSizeMigrationTaskV2(Context context) { + + } + + /** + * Migrates the workspace and hotseat in case their sizes changed. + * + * @return false if the migration failed. + */ + public static boolean migrateGridIfNeeded(Context context) { + // To be implemented. + return true; + } +} diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 23ec459602..ec23f98df5 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -19,6 +19,7 @@ package com.android.launcher3.model; import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER; import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE; import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED; +import static com.android.launcher3.config.FeatureFlags.MULTI_DB_GRID_MIRATION_ALGO; import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import static com.android.launcher3.util.PackageManagerHelper.hasShortcutsPermission; @@ -320,7 +321,9 @@ public class LoaderTask implements Runnable { clearDb = true; } - if (!clearDb && !GridSizeMigrationTask.migrateGridIfNeeded(context)) { + if (!clearDb && (MULTI_DB_GRID_MIRATION_ALGO.get() + ? !GridSizeMigrationTaskV2.migrateGridIfNeeded(context) + : !GridSizeMigrationTask.migrateGridIfNeeded(context))) { // Migration failed. Clear workspace. clearDb = true; } diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index 407ff3153d..842be40a0c 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -107,15 +107,17 @@ public class RestoreDbTask { */ private void backupWorkspace(Context context, SQLiteDatabase db) throws Exception { InvariantDeviceProfile idp = LauncherAppState.getIDP(context); - new GridBackupTable(context, db, idp.numHotseatIcons, idp.numColumns, idp.numRows) + // TODO(pinyaoting): Support backing up workspace with multiple grid options. + new GridBackupTable(context, db, db, idp.numHotseatIcons, idp.numColumns, idp.numRows) .doBackup(getDefaultProfileId(db), GridBackupTable.OPTION_REQUIRES_SANITIZATION); } private void restoreWorkspace(@NonNull Context context, @NonNull SQLiteDatabase db, @NonNull DatabaseHelper helper, @NonNull BackupManager backupManager) throws Exception { + // TODO(pinyaoting): Support restoring workspace with multiple grid options. final InvariantDeviceProfile idp = LauncherAppState.getIDP(context); - GridBackupTable backupTable = new GridBackupTable(context, db, + GridBackupTable backupTable = new GridBackupTable(context, db, db, idp.numHotseatIcons, idp.numColumns, idp.numRows); if (backupTable.restoreFromRawBackupIfAvailable(getDefaultProfileId(db))) { sanitizeDB(helper, db, backupManager); From 5c052b4a2ef0748a33c2688e00c5c0f4e30a8c47 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 6 Feb 2020 14:04:47 -0800 Subject: [PATCH 05/51] Removing multidex support Bug: 148912608 Change-Id: Ib9ab922ec0c3b0f3c5e4a8f5ebc6220cac1e5516 --- Android.mk | 4 ++-- .../src/com/android/quickstep/LauncherSwipeHandler.java | 4 +--- quickstep/src/com/android/quickstep/SystemUiProxy.java | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Android.mk b/Android.mk index a099ada991..66ccae038f 100644 --- a/Android.mk +++ b/Android.mk @@ -144,7 +144,7 @@ LOCAL_USE_AAPT2 := true LOCAL_AAPT2_ONLY := true LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLibLauncherWrapper launcherprotosnano +LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano ifneq (,$(wildcard frameworks/base)) LOCAL_PRIVATE_PLATFORM_APIS := true else @@ -213,7 +213,7 @@ include $(CLEAR_VARS) LOCAL_USE_AAPT2 := true LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLibLauncherWrapper launcherprotosnano +LOCAL_STATIC_JAVA_LIBRARIES := SystemUISharedLib launcherprotosnano ifneq (,$(wildcard frameworks/base)) LOCAL_PRIVATE_PLATFORM_APIS := true else diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java index 1b60404556..f0516acf7b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandler.java @@ -75,7 +75,6 @@ import com.android.quickstep.inputconsumers.OverviewInputConsumer; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.AppWindowAnimationHelper.TargetAlphaProvider; import com.android.quickstep.util.RectFSpringAnim; -import com.android.quickstep.util.SharedApiCompat; import com.android.quickstep.util.ShelfPeekAnim; import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState; import com.android.quickstep.views.LiveTileOverlay; @@ -1142,8 +1141,7 @@ public class LauncherSwipeHandler final int runningTaskId = mGestureState.getRunningTaskId(); if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { if (mRecentsAnimationController != null) { - SharedApiCompat.setWillFinishToHome(mRecentsAnimationController.getController(), - true /* willFinishToHome */); + mRecentsAnimationController.getController().setWillFinishToHome(true); // Update the screenshot of the task if (mTaskSnapshot == null) { mTaskSnapshot = mRecentsAnimationController.screenshotTask(runningTaskId); diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 3c6537a72d..101bb075a0 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -29,7 +29,6 @@ import android.util.Log; import android.view.MotionEvent; import com.android.launcher3.util.MainThreadInitializedObject; -import com.android.quickstep.util.SharedApiCompat; import com.android.systemui.shared.recents.ISystemUiProxy; /** @@ -278,7 +277,7 @@ public class SystemUiProxy implements ISystemUiProxy { mLastShelfVisible = visible; mLastShelfHeight = shelfHeight; try { - SharedApiCompat.setShelfHeight(mSystemUiProxy, visible, shelfHeight); + mSystemUiProxy.setShelfHeight(visible, shelfHeight); } catch (RemoteException e) { Log.w(TAG, "Failed call setShelfHeight visible: " + visible + " height: " + shelfHeight, e); From 18204e4eeaaea47a55dc1f217f6a79d00043e5b0 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Thu, 6 Feb 2020 11:28:01 -0800 Subject: [PATCH 06/51] Various icon cache fixes > Multiple instances of LauncherIcon created when LauncherIcons refers IconCache which in turn creates new LauncherIcons > Widget icons are never cached as they were using low res icons > Shortcut drag icons are not loaded synchronously when using PinItemRequest flow > Wrong lastUpdatedTime is used in iconCache for shortcuts > IconUpdateHandler does not ignore managedUser promise icons Change-Id: Ie7eed68a30fad11d1861b6c70c380953a15ae1cf --- .../android/launcher3/model/WidgetsModel.java | 4 +- .../launcher3/icons/BaseIconFactory.java | 11 ++ .../launcher3/icons/cache/BaseIconCache.java | 13 +- .../launcher3/icons/cache/CachingLogic.java | 4 + .../icons/cache/IconCacheUpdateHandler.java | 17 ++- .../appprediction/DynamicItemCache.java | 10 +- .../launcher3/InstallShortcutReceiver.java | 12 +- .../LauncherAppWidgetProviderInfo.java | 11 +- src/com/android/launcher3/LauncherModel.java | 5 +- src/com/android/launcher3/Utilities.java | 5 +- .../launcher3/icons/ComponentWithLabel.java | 10 +- .../icons/ComponentWithLabelAndIcon.java | 54 ++++++++ .../android/launcher3/icons/IconCache.java | 76 +++++++++++ .../launcher3/icons/LauncherIcons.java | 127 ------------------ .../launcher3/icons/ShortcutCachingLogic.java | 7 + .../android/launcher3/model/LoaderCursor.java | 52 ++++--- .../android/launcher3/model/LoaderTask.java | 35 ++--- .../launcher3/model/ShortcutsChangedTask.java | 8 +- .../model/UserLockStateChangedTask.java | 7 +- .../launcher3/pm/PinRequestHelper.java | 18 +-- .../pm/ShortcutConfigActivityInfo.java | 5 +- .../launcher3/popup/PopupPopulator.java | 9 +- .../android/launcher3/util/ShortcutUtil.java | 24 ---- .../android/launcher3/model/WidgetsModel.java | 7 +- 24 files changed, 250 insertions(+), 281 deletions(-) create mode 100644 src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java index 7269b417e4..7690b9d57c 100644 --- a/go/src/com/android/launcher3/model/WidgetsModel.java +++ b/go/src/com/android/launcher3/model/WidgetsModel.java @@ -22,7 +22,7 @@ import android.os.UserHandle; import androidx.annotation.Nullable; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.icons.ComponentWithLabel; +import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.widget.WidgetListRowEntry; @@ -59,7 +59,7 @@ public class WidgetsModel { * @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise * only widgets and shortcuts associated with the package/user are. */ - public List update(LauncherAppState app, + public List update(LauncherAppState app, @Nullable PackageUserKey packageUser) { return Collections.emptyList(); } diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java index bce4e0f330..31a923e314 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java @@ -350,6 +350,17 @@ public class BaseIconFactory implements AutoCloseable { iconDpi); } + /** + * Badges the provided source with the badge info + */ + public BitmapInfo badgeBitmap(Bitmap source, BitmapInfo badgeInfo) { + Bitmap icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> { + getShadowGenerator().recreateIcon(source, c); + badgeWithDrawable(c, new FixedSizeBitmapDrawable(badgeInfo.icon)); + }); + return BitmapInfo.of(icon, badgeInfo.color); + } + private int extractColor(Bitmap bitmap) { return mDisableColorExtractor ? 0 : mColorExtractor.findDominantColorByHue(bitmap); } diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java index e807791d94..4c634cbc26 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java +++ b/iconloaderlib/src/com/android/launcher3/icons/cache/BaseIconCache.java @@ -281,7 +281,8 @@ public abstract class BaseIconCache { ContentValues values = newContentValues(entry.bitmap, entry.title.toString(), componentName.getPackageName(), cachingLogic.getKeywords(object, mLocaleList)); - addIconToDB(values, componentName, info, userSerial); + addIconToDB(values, componentName, info, userSerial, + cachingLogic.getLastUpdatedTime(object, info)); } /** @@ -289,10 +290,10 @@ public abstract class BaseIconCache { * @param values {@link ContentValues} containing icon & title */ private void addIconToDB(ContentValues values, ComponentName key, - PackageInfo info, long userSerial) { + PackageInfo info, long userSerial, long lastUpdateTime) { values.put(IconDB.COLUMN_COMPONENT, key.flattenToString()); values.put(IconDB.COLUMN_USER, userSerial); - values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime); + values.put(IconDB.COLUMN_LAST_UPDATED, lastUpdateTime); values.put(IconDB.COLUMN_VERSION, info.versionCode); mIconDb.insertOrReplace(values); } @@ -362,7 +363,8 @@ public abstract class BaseIconCache { } if (object != null) { entry.title = cachingLogic.getLabel(object); - entry.contentDescription = mPackageManager.getUserBadgedLabel(entry.title, user); + entry.contentDescription = mPackageManager.getUserBadgedLabel( + cachingLogic.getDescription(object, entry.title), user); } } } @@ -449,7 +451,8 @@ public abstract class BaseIconCache { // package updates. ContentValues values = newContentValues( iconInfo, entry.title.toString(), packageName, null); - addIconToDB(values, cacheKey.componentName, info, getSerialNumberForUser(user)); + addIconToDB(values, cacheKey.componentName, info, getSerialNumberForUser(user), + info.lastUpdateTime); } catch (NameNotFoundException e) { if (DEBUG) Log.d(TAG, "Application not installed " + packageName); diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java index a89ede7b34..c12e9dcc15 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java +++ b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java @@ -34,6 +34,10 @@ public interface CachingLogic { CharSequence getLabel(T object); + default CharSequence getDescription(T object, CharSequence fallback) { + return fallback; + } + @NonNull BitmapInfo loadIcon(Context context, T object); diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java index bcdbce5e29..aec1cddce4 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java +++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java @@ -24,6 +24,7 @@ import android.database.sqlite.SQLiteException; import android.os.SystemClock; import android.os.UserHandle; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; import android.util.SparseBooleanArray; @@ -61,7 +62,7 @@ public class IconCacheUpdateHandler { private final HashMap mPkgInfoMap; private final BaseIconCache mIconCache; - private final HashMap> mPackagesToIgnore = new HashMap<>(); + private final ArrayMap> mPackagesToIgnore = new ArrayMap<>(); private final SparseBooleanArray mItemsToDelete = new SparseBooleanArray(); private boolean mFilterMode = MODE_SET_INVALID_ITEMS; @@ -77,8 +78,16 @@ public class IconCacheUpdateHandler { createPackageInfoMap(); } - public void setPackagesToIgnore(UserHandle userHandle, Set packages) { - mPackagesToIgnore.put(userHandle, packages); + /** + * Sets a package to ignore for processing + */ + public void addPackagesToIgnore(UserHandle userHandle, String packageName) { + Set packages = mPackagesToIgnore.get(userHandle); + if (packages == null) { + packages = new HashSet<>(); + mPackagesToIgnore.put(userHandle, packages); + } + packages.add(packageName); } private void createPackageInfoMap() { @@ -181,6 +190,7 @@ public class IconCacheUpdateHandler { } continue; } + if (app == null) { if (mFilterMode == MODE_SET_INVALID_ITEMS) { mIconCache.remove(component, user); @@ -263,6 +273,7 @@ public class IconCacheUpdateHandler { T app = mAppsToUpdate.pop(); String pkg = mCachingLogic.getComponent(app).getPackageName(); PackageInfo info = mPkgInfoMap.get(pkg); + mIconCache.addIconToDBAndMemCache( app, mCachingLogic, info, mUserSerial, true /*replace existing*/); mUpdatedPackages.add(pkg); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java index 76972aff41..54f58e2081 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java @@ -43,7 +43,6 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.allapps.AllAppsStore; import com.android.launcher3.icons.IconCache; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.util.InstantAppResolver; @@ -170,14 +169,7 @@ public class DynamicItemCache { List details = shortcutKey.buildRequest(mContext).query(ShortcutRequest.ALL); if (!details.isEmpty()) { WorkspaceItemInfo si = new WorkspaceItemInfo(details.get(0), mContext); - try (LauncherIcons li = LauncherIcons.obtain(mContext)) { - si.bitmap = li.createShortcutIcon(details.get(0), true /* badged */, null); - } catch (Exception e) { - if (DEBUG) { - Log.e(TAG, "Error loading shortcut icon for " + shortcutKey.toString()); - } - return null; - } + mIconCache.getShortcutIcon(si, details.get(0)); return si; } if (DEBUG) { diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index 3eb02b3dae..a5142d815c 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -17,7 +17,6 @@ package com.android.launcher3; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; -import static com.android.launcher3.util.ShortcutUtil.fetchAndUpdateShortcutIconAsync; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; @@ -44,7 +43,6 @@ import android.util.Pair; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.GraphicsUtils; import com.android.launcher3.icons.LauncherIcons; @@ -61,7 +59,6 @@ import org.json.JSONStringer; import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -491,13 +488,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver { return Pair.create(si, null); } else if (shortcutInfo != null) { WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, mContext); - if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) { - fetchAndUpdateShortcutIconAsync(mContext, itemInfo, shortcutInfo, true); - } else { - LauncherIcons li = LauncherIcons.obtain(mContext); - itemInfo.bitmap = li.createShortcutIcon(shortcutInfo); - li.recycle(); - } + LauncherAppState.getInstance(mContext).getIconCache().getShortcutIcon( + itemInfo, shortcutInfo); return Pair.create(itemInfo, shortcutInfo); } else if (providerInfo != null) { LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo diff --git a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java index 228c07ec43..56cce78659 100644 --- a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java +++ b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java @@ -7,10 +7,12 @@ import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Point; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.UserHandle; -import com.android.launcher3.icons.ComponentWithLabel; +import com.android.launcher3.icons.ComponentWithLabelAndIcon; +import com.android.launcher3.icons.IconCache; /** * This class is a thin wrapper around the framework AppWidgetProviderInfo class. This class affords @@ -19,7 +21,7 @@ import com.android.launcher3.icons.ComponentWithLabel; * as opposed to a widget instance, and so should not be confused with {@link LauncherAppWidgetInfo} */ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo - implements ComponentWithLabel { + implements ComponentWithLabelAndIcon { public static final String CLS_CUSTOM_WIDGET_PREFIX = "#custom-widget-"; @@ -111,4 +113,9 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo public final UserHandle getUser() { return getProfile(); } + + @Override + public Drawable getFullResIcon(IconCache cache) { + return cache.getFullResIcon(provider.getPackageName(), icon); + } } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 04a7ecd826..efe85c7f7c 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -37,7 +37,6 @@ import androidx.annotation.WorkerThread; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.IconCache; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.AddWorkspaceItemsTask; import com.android.launcher3.model.AllAppsList; @@ -573,9 +572,7 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi public void updateAndBindWorkspaceItem(WorkspaceItemInfo si, ShortcutInfo info) { updateAndBindWorkspaceItem(() -> { si.updateFromDeepShortcutInfo(info, mApp.getContext()); - LauncherIcons li = LauncherIcons.obtain(mApp.getContext()); - si.bitmap = li.createShortcutIcon(info); - li.recycle(); + mApp.getIconCache().getShortcutIcon(si, info); return si; }); } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 7f443b60b8..e0e4cc0ce4 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -584,9 +584,8 @@ public final class Utilities { return new FixedSizeEmptyDrawable(iconSize); } ShortcutInfo si = (ShortcutInfo) obj; - LauncherIcons li = LauncherIcons.obtain(appState.getContext()); - Bitmap badge = li.getShortcutInfoBadge(si, appState.getIconCache()).bitmap.icon; - li.recycle(); + Bitmap badge = LauncherAppState.getInstance(appState.getContext()) + .getIconCache().getShortcutInfoBadge(si).icon; float badgeSize = LauncherIcons.getBadgeSizeForIconSize(iconSize); float insetFraction = (iconSize - badgeSize) / iconSize; return new InsetDrawable(new FastBitmapDrawable(badge), diff --git a/src/com/android/launcher3/icons/ComponentWithLabel.java b/src/com/android/launcher3/icons/ComponentWithLabel.java index f7ee5f9329..372c59166e 100644 --- a/src/com/android/launcher3/icons/ComponentWithLabel.java +++ b/src/com/android/launcher3/icons/ComponentWithLabel.java @@ -31,7 +31,7 @@ public interface ComponentWithLabel { CharSequence getLabel(PackageManager pm); - class ComponentCachingLogic implements CachingLogic { + class ComponentCachingLogic implements CachingLogic { private final PackageManager mPackageManager; private final boolean mAddToMemCache; @@ -42,22 +42,22 @@ public interface ComponentWithLabel { } @Override - public ComponentName getComponent(ComponentWithLabel object) { + public ComponentName getComponent(T object) { return object.getComponent(); } @Override - public UserHandle getUser(ComponentWithLabel object) { + public UserHandle getUser(T object) { return object.getUser(); } @Override - public CharSequence getLabel(ComponentWithLabel object) { + public CharSequence getLabel(T object) { return object.getLabel(mPackageManager); } @Override - public BitmapInfo loadIcon(Context context, ComponentWithLabel object) { + public BitmapInfo loadIcon(Context context, T object) { return BitmapInfo.LOW_RES_INFO; } diff --git a/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java b/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java new file mode 100644 index 0000000000..248a57d2fd --- /dev/null +++ b/src/com/android/launcher3/icons/ComponentWithLabelAndIcon.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.icons; + +import android.content.Context; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; + +import com.android.launcher3.LauncherAppState; + +/** + * Extension of ComponentWithLabel to also support loading icons + */ +public interface ComponentWithLabelAndIcon extends ComponentWithLabel { + + /** + * Provide an icon for this object + */ + Drawable getFullResIcon(IconCache cache); + + class ComponentWithIconCachingLogic extends ComponentCachingLogic { + + public ComponentWithIconCachingLogic(Context context, boolean addToMemCache) { + super(context, addToMemCache); + } + + @NonNull + @Override + public BitmapInfo loadIcon(Context context, ComponentWithLabelAndIcon object) { + Drawable d = object.getFullResIcon(LauncherAppState.getInstance(context) + .getIconCache()); + if (d == null) { + return super.loadIcon(context, object); + } + try (LauncherIcons li = LauncherIcons.obtain(context)) { + return li.createBadgedIconBitmap(d, object.getUser(), 0); + } + } + } +} diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java index 69b812541e..804acc3d8c 100644 --- a/src/com/android/launcher3/icons/IconCache.java +++ b/src/com/android/launcher3/icons/IconCache.java @@ -19,6 +19,7 @@ package com.android.launcher3.icons; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -56,6 +57,7 @@ import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; +import java.util.function.Predicate; import java.util.function.Supplier; /** @@ -65,6 +67,9 @@ public class IconCache extends BaseIconCache { private static final String TAG = "Launcher.IconCache"; + private final Predicate mIsUsingFallbackIconCheck = w -> w.bitmap != null + && w.bitmap.isNullOrLowRes() && !isDefaultIcon(w.bitmap, w.user); + private final CachingLogic mComponentWithLabelCachingLogic; private final CachingLogic mLauncherActivityInfoCachingLogic; private final CachingLogic mShortcutCachingLogic; @@ -179,6 +184,77 @@ public class IconCache extends BaseIconCache { getTitleAndIcon(info, () -> activityInfo, false, useLowResIcon); } + /** + * Fill in {@param info} with the icon for {@param si} + */ + public void getShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) { + getShortcutIcon(info, si, true, mIsUsingFallbackIconCheck); + } + + /** + * Fill in {@param info} with an unbadged icon for {@param si} + */ + public void getUnbadgedShortcutIcon(ItemInfoWithIcon info, ShortcutInfo si) { + getShortcutIcon(info, si, false, mIsUsingFallbackIconCheck); + } + + /** + * Fill in {@param info} with the icon and label for {@param si}. If the icon is not + * available, and fallback check returns true, it keeps the old icon. + */ + public void getShortcutIcon(T info, ShortcutInfo si, + @NonNull Predicate fallbackIconCheck) { + getShortcutIcon(info, si, true /* use badged */, fallbackIconCheck); + } + + private synchronized void getShortcutIcon(T info, ShortcutInfo si, + boolean useBadged, @NonNull Predicate fallbackIconCheck) { + BitmapInfo bitmapInfo; + if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) { + bitmapInfo = cacheLocked(ShortcutKey.fromInfo(si).componentName, si.getUserHandle(), + () -> si, mShortcutCachingLogic, false, false).bitmap; + } else { + // If caching is disabled, load the full icon + bitmapInfo = mShortcutCachingLogic.loadIcon(mContext, si); + } + if (bitmapInfo.isNullOrLowRes()) { + bitmapInfo = getDefaultIcon(si.getUserHandle()); + } + + if (isDefaultIcon(bitmapInfo, si.getUserHandle()) && fallbackIconCheck.test(info)) { + return; + } + info.bitmap = bitmapInfo; + if (useBadged) { + BitmapInfo badgeInfo = getShortcutInfoBadge(si); + try (LauncherIcons li = LauncherIcons.obtain(mContext)) { + info.bitmap = li.badgeBitmap(info.bitmap.icon, badgeInfo); + } + } + } + + /** + * Returns the badging info for the shortcut + */ + public BitmapInfo getShortcutInfoBadge(ShortcutInfo shortcutInfo) { + ComponentName cn = shortcutInfo.getActivity(); + if (cn != null) { + // Get the app info for the source activity. + AppInfo appInfo = new AppInfo(); + appInfo.user = shortcutInfo.getUserHandle(); + appInfo.componentName = cn; + appInfo.intent = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER) + .setComponent(cn); + getTitleAndIcon(appInfo, false); + return appInfo.bitmap; + } else { + PackageItemInfo pkgInfo = new PackageItemInfo(shortcutInfo.getPackage()); + getTitleAndIconForApp(pkgInfo, false); + return pkgInfo.bitmap; + } + } + /** * Fill in info with the icon and label for deep shortcut. */ diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java index e67d2445b7..cbd7c530c5 100644 --- a/src/com/android/launcher3/icons/LauncherIcons.java +++ b/src/com/android/launcher3/icons/LauncherIcons.java @@ -16,28 +16,11 @@ package com.android.launcher3.icons; -import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.pm.ShortcutInfo; -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.os.Process; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; - -import com.android.launcher3.AppInfo; -import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.ItemInfoWithIcon; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.graphics.IconShape; -import com.android.launcher3.model.PackageItemInfo; -import com.android.launcher3.util.Themes; - -import java.util.function.Supplier; /** * Wrapper class to provide access to {@link BaseIconFactory} and also to provide pool of this class @@ -111,114 +94,4 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable { public void close() { recycle(); } - - // below methods should also migrate to BaseIconFactory - public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo) { - return createShortcutIcon(shortcutInfo, true /* badged */); - } - - public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged) { - return createShortcutIcon(shortcutInfo, badged, null); - } - - public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged, - @Nullable Supplier fallbackIconProvider) { - if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) { - return createShortcutIconCached(shortcutInfo, badged, true, fallbackIconProvider); - } else { - return createShortcutIconLegacy(shortcutInfo, badged, fallbackIconProvider); - } - } - - public BitmapInfo createShortcutIconLegacy(ShortcutInfo shortcutInfo, boolean badged, - @Nullable Supplier fallbackIconProvider) { - Drawable unbadgedDrawable = ShortcutCachingLogic.getIcon( - mContext, shortcutInfo, mFillResIconDpi); - IconCache cache = LauncherAppState.getInstance(mContext).getIconCache(); - final Bitmap unbadgedBitmap; - if (unbadgedDrawable != null) { - unbadgedBitmap = createScaledBitmapWithoutShadow(unbadgedDrawable, 0); - } else { - if (fallbackIconProvider != null) { - // Fallback icons are already badged and with appropriate shadow - ItemInfoWithIcon fullIcon = fallbackIconProvider.get(); - if (fullIcon != null && fullIcon.bitmap != null) { - return fullIcon.bitmap; - } - } - unbadgedBitmap = cache.getDefaultIcon(Process.myUserHandle()).icon; - } - - if (!badged) { - return BitmapInfo.of(unbadgedBitmap, Themes.getColorAccent(mContext)); - } - - final Bitmap unbadgedfinal = unbadgedBitmap; - final ItemInfoWithIcon badge = getShortcutInfoBadge(shortcutInfo, cache); - - Bitmap icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> { - getShadowGenerator().recreateIcon(unbadgedfinal, c); - badgeWithDrawable(c, new FastBitmapDrawable(badge.bitmap)); - }); - return BitmapInfo.of(icon, badge.bitmap.color); - } - - @WorkerThread - public BitmapInfo createShortcutIconCached(ShortcutInfo shortcutInfo, boolean badged, - boolean useCache, @Nullable Supplier fallbackIconProvider) { - IconCache cache = LauncherAppState.getInstance(mContext).getIconCache(); - final BitmapInfo bitmapInfo; - if (useCache) { - bitmapInfo = cache.getDeepShortcutTitleAndIcon(shortcutInfo).bitmap; - } else { - bitmapInfo = new ShortcutCachingLogic().loadIcon(mContext, shortcutInfo); - } - final Bitmap unbadgedBitmap; - if (bitmapInfo.icon != null) { - unbadgedBitmap = bitmapInfo.icon; - } else { - if (fallbackIconProvider != null) { - // Fallback icons are already badged and with appropriate shadow - ItemInfoWithIcon fullIcon = fallbackIconProvider.get(); - if (fullIcon != null && fullIcon.bitmap != null) { - return fullIcon.bitmap; - } - } - unbadgedBitmap = cache.getDefaultIcon(Process.myUserHandle()).icon; - } - - if (!badged) { - return BitmapInfo.of(unbadgedBitmap, Themes.getColorAccent(mContext)); - } - - final Bitmap unbadgedfinal = unbadgedBitmap; - final ItemInfoWithIcon badge = getShortcutInfoBadge(shortcutInfo, cache); - - Bitmap icon = BitmapRenderer.createHardwareBitmap(mIconBitmapSize, mIconBitmapSize, (c) -> { - getShadowGenerator().recreateIcon(unbadgedfinal, c); - badgeWithDrawable(c, new FastBitmapDrawable(badge.bitmap)); - }); - return BitmapInfo.of(icon, badge.bitmap.color); - } - - public ItemInfoWithIcon getShortcutInfoBadge(ShortcutInfo shortcutInfo, IconCache cache) { - ComponentName cn = shortcutInfo.getActivity(); - String badgePkg = shortcutInfo.getPackage(); - boolean hasBadgePkgSet = !badgePkg.equals(shortcutInfo.getPackage()); - if (cn != null && !hasBadgePkgSet) { - // Get the app info for the source activity. - AppInfo appInfo = new AppInfo(); - appInfo.user = shortcutInfo.getUserHandle(); - appInfo.componentName = cn; - appInfo.intent = new Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_LAUNCHER) - .setComponent(cn); - cache.getTitleAndIcon(appInfo, false); - return appInfo; - } else { - PackageItemInfo pkgInfo = new PackageItemInfo(badgePkg); - cache.getTitleAndIconForApp(pkgInfo, false); - return pkgInfo; - } - } } diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java index b856dd1318..d7eed06901 100644 --- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java +++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java @@ -25,6 +25,7 @@ import android.content.pm.PackageInfo; import android.content.pm.ShortcutInfo; import android.graphics.drawable.Drawable; import android.os.UserHandle; +import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; @@ -57,6 +58,12 @@ public class ShortcutCachingLogic implements CachingLogic { return info.getShortLabel(); } + @Override + public CharSequence getDescription(ShortcutInfo object, CharSequence fallback) { + CharSequence label = object.getLongLabel(); + return TextUtils.isEmpty(label) ? fallback : label; + } + @NonNull @Override public BitmapInfo loadIcon(Context context, ShortcutInfo info) { diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java index 95268d088e..49614327ff 100644 --- a/src/com/android/launcher3/model/LoaderCursor.java +++ b/src/com/android/launcher3/model/LoaderCursor.java @@ -16,6 +16,8 @@ package com.android.launcher3.model; +import static android.graphics.BitmapFactory.decodeByteArray; + import android.content.ComponentName; import android.content.ContentValues; import android.content.Context; @@ -26,7 +28,6 @@ import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.database.Cursor; import android.database.CursorWrapper; -import android.graphics.BitmapFactory; import android.os.UserHandle; import android.provider.BaseColumns; import android.text.TextUtils; @@ -166,37 +167,30 @@ public class LoaderCursor extends CursorWrapper { */ protected boolean loadIcon(WorkspaceItemInfo info) { try (LauncherIcons li = LauncherIcons.obtain(mContext)) { - return loadIcon(info, li); - } - } - - /** - * Loads the icon from the cursor and updates the {@param info} if the icon is an app resource. - */ - protected boolean loadIcon(WorkspaceItemInfo info, LauncherIcons li) { - if (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { - String packageName = getString(iconPackageIndex); - String resourceName = getString(iconResourceIndex); - if (!TextUtils.isEmpty(packageName) || !TextUtils.isEmpty(resourceName)) { - info.iconResource = new ShortcutIconResource(); - info.iconResource.packageName = packageName; - info.iconResource.resourceName = resourceName; - BitmapInfo iconInfo = li.createIconBitmap(info.iconResource); - if (iconInfo != null) { - info.bitmap = iconInfo; - return true; + if (itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { + String packageName = getString(iconPackageIndex); + String resourceName = getString(iconResourceIndex); + if (!TextUtils.isEmpty(packageName) || !TextUtils.isEmpty(resourceName)) { + info.iconResource = new ShortcutIconResource(); + info.iconResource.packageName = packageName; + info.iconResource.resourceName = resourceName; + BitmapInfo iconInfo = li.createIconBitmap(info.iconResource); + if (iconInfo != null) { + info.bitmap = iconInfo; + return true; + } } } - } - // Failed to load from resource, try loading from DB. - byte[] data = getBlob(iconIndex); - try { - info.bitmap = li.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length)); - return true; - } catch (Exception e) { - Log.e(TAG, "Failed to decode byte array for info " + info, e); - return false; + // Failed to load from resource, try loading from DB. + byte[] data = getBlob(iconIndex); + try { + info.bitmap = li.createIconBitmap(decodeByteArray(data, 0, data.length)); + return true; + } catch (Exception e) { + Log.e(TAG, "Failed to decode byte array for info " + info, e); + return false; + } } } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 23ec459602..8728b9387b 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -35,7 +35,6 @@ import android.content.pm.LauncherApps; import android.content.pm.PackageInstaller; import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.ShortcutInfo; -import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; @@ -50,7 +49,6 @@ import com.android.launcher3.AppInfo; import com.android.launcher3.FolderInfo; import com.android.launcher3.InstallShortcutReceiver; import com.android.launcher3.ItemInfo; -import com.android.launcher3.ItemInfoWithIcon; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherModel; @@ -61,11 +59,10 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderGridOrganizer; import com.android.launcher3.folder.FolderNameProvider; -import com.android.launcher3.icons.ComponentWithLabel; -import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic; +import com.android.launcher3.icons.ComponentWithLabelAndIcon; +import com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic; import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.LauncherActivityCachingLogic; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.icons.ShortcutCachingLogic; import com.android.launcher3.icons.cache.IconCacheUpdateHandler; import com.android.launcher3.logging.FileLog; @@ -94,7 +91,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.concurrent.CancellationException; -import java.util.function.Supplier; /** * Runnable for the thread that loads the contents of the launcher: @@ -263,7 +259,8 @@ public class LoaderTask implements Runnable { verifyNotStopped(); // fourth step - List allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null); + List allWidgetsList = + mBgDataModel.widgetsModel.update(mApp, null); logger.addSplit("load widgets"); verifyNotStopped(); @@ -271,8 +268,9 @@ public class LoaderTask implements Runnable { logger.addSplit("bindWidgets"); verifyNotStopped(); - updateHandler.updateIcons(allWidgetsList, new ComponentCachingLogic( - mApp.getContext(), true), mApp.getModel()::onWidgetLabelsUpdated); + updateHandler.updateIcons(allWidgetsList, + new ComponentWithIconCachingLogic(mApp.getContext(), true), + mApp.getModel()::onWidgetLabelsUpdated); logger.addSplit("save widgets in icon cache"); // fifth step @@ -544,17 +542,10 @@ public class LoaderTask implements Runnable { continue; } info = new WorkspaceItemInfo(pinnedShortcut, context); - final WorkspaceItemInfo finalInfo = info; - - LauncherIcons li = LauncherIcons.obtain(context); // If the pinned deep shortcut is no longer published, // use the last saved icon instead of the default. - Supplier fallbackIconProvider = () -> - c.loadIcon(finalInfo, li) ? finalInfo : null; - info.bitmap = li.createShortcutIcon( - pinnedShortcut, true /* badged */, - fallbackIconProvider); - li.recycle(); + mIconCache.getShortcutIcon(info, pinnedShortcut, c::loadIcon); + if (pmHelper.isAppSuspended( pinnedShortcut.getPackage(), info.user)) { info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED; @@ -854,23 +845,23 @@ public class LoaderTask implements Runnable { private void setIgnorePackages(IconCacheUpdateHandler updateHandler) { // Ignore packages which have a promise icon. - HashSet packagesToIgnore = new HashSet<>(); synchronized (mBgDataModel) { for (ItemInfo info : mBgDataModel.itemsIdMap) { if (info instanceof WorkspaceItemInfo) { WorkspaceItemInfo si = (WorkspaceItemInfo) info; if (si.isPromise() && si.getTargetComponent() != null) { - packagesToIgnore.add(si.getTargetComponent().getPackageName()); + updateHandler.addPackagesToIgnore( + si.user, si.getTargetComponent().getPackageName()); } } else if (info instanceof LauncherAppWidgetInfo) { LauncherAppWidgetInfo lawi = (LauncherAppWidgetInfo) info; if (lawi.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) { - packagesToIgnore.add(lawi.providerName.getPackageName()); + updateHandler.addPackagesToIgnore( + lawi.user, lawi.providerName.getPackageName()); } } } } - updateHandler.setPackagesToIgnore(Process.myUserHandle(), packagesToIgnore); } private List loadAllApps() { diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java index b0e7a69f81..3f79ad020d 100644 --- a/src/com/android/launcher3/model/ShortcutsChangedTask.java +++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java @@ -23,7 +23,6 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.util.ItemInfoMatcher; @@ -89,12 +88,7 @@ public class ShortcutsChangedTask extends BaseModelUpdateTask { } for (final WorkspaceItemInfo workspaceItemInfo : workspaceItemInfos) { workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context); - // If the shortcut is pinned but no longer has an icon in the system, - // keep the current icon instead of reverting to the default icon. - LauncherIcons li = LauncherIcons.obtain(context); - workspaceItemInfo.bitmap = li.createShortcutIcon( - fullDetails, true, () -> workspaceItemInfo); - li.recycle(); + app.getIconCache().getShortcutIcon(workspaceItemInfo, fullDetails); updatedWorkspaceItemInfos.add(workspaceItemInfo); } } diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java index d527423e42..a3adc823dd 100644 --- a/src/com/android/launcher3/model/UserLockStateChangedTask.java +++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java @@ -26,7 +26,6 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutRequest; import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult; @@ -89,11 +88,7 @@ public class UserLockStateChangedTask extends BaseModelUpdateTask { } si.runtimeStatusFlags &= ~FLAG_DISABLED_LOCKED_USER; si.updateFromDeepShortcutInfo(shortcut, context); - // If the shortcut is pinned but no longer has an icon in the system, - // keep the current icon instead of reverting to the default icon. - LauncherIcons li = LauncherIcons.obtain(context); - si.bitmap = li.createShortcutIcon(shortcut, true, () -> si); - li.recycle(); + app.getIconCache().getShortcutIcon(si, shortcut); } else { si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER; } diff --git a/src/com/android/launcher3/pm/PinRequestHelper.java b/src/com/android/launcher3/pm/PinRequestHelper.java index a15399d042..74a5a31b60 100644 --- a/src/com/android/launcher3/pm/PinRequestHelper.java +++ b/src/com/android/launcher3/pm/PinRequestHelper.java @@ -17,7 +17,6 @@ package com.android.launcher3.pm; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; -import static com.android.launcher3.util.ShortcutUtil.fetchAndUpdateShortcutIconAsync; import android.annotation.TargetApi; import android.content.Context; @@ -32,8 +31,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.LauncherAppState; import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.icons.LauncherIcons; +import com.android.launcher3.icons.ShortcutCachingLogic; public class PinRequestHelper { @@ -82,16 +80,10 @@ public class PinRequestHelper { ShortcutInfo si = request.getShortcutInfo(); WorkspaceItemInfo info = new WorkspaceItemInfo(si, context); - // Apply the unbadged icon and fetch the actual icon asynchronously. - if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) { - fetchAndUpdateShortcutIconAsync(context, info, si, false); - } else { - LauncherIcons li = LauncherIcons.obtain(context); - info.bitmap = li.createShortcutIcon(si, false /* badged */); - li.recycle(); - LauncherAppState.getInstance(context).getModel() - .updateAndBindWorkspaceItem(info, si); - } + // Apply the unbadged icon synchronously using the caching logic directly and + // fetch the actual icon asynchronously. + info.bitmap = new ShortcutCachingLogic().loadIcon(context, si); + LauncherAppState.getInstance(context).getModel().updateAndBindWorkspaceItem(info, si); return info; } else { return null; diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java index b563171bd1..ac0e0652c8 100644 --- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java +++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java @@ -41,7 +41,7 @@ import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.icons.ComponentWithLabel; +import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.icons.IconCache; import com.android.launcher3.util.PackageUserKey; @@ -51,7 +51,7 @@ import java.util.List; /** * Wrapper class for representing a shortcut configure activity. */ -public abstract class ShortcutConfigActivityInfo implements ComponentWithLabel { +public abstract class ShortcutConfigActivityInfo implements ComponentWithLabelAndIcon { private static final String TAG = "SCActivityInfo"; @@ -77,6 +77,7 @@ public abstract class ShortcutConfigActivityInfo implements ComponentWithLabel { return LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; } + @Override public abstract Drawable getFullResIcon(IconCache cache); /** diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java index 9faeb4059c..fdcf04ff71 100644 --- a/src/com/android/launcher3/popup/PopupPopulator.java +++ b/src/com/android/launcher3/popup/PopupPopulator.java @@ -26,8 +26,9 @@ import androidx.annotation.VisibleForTesting; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.ItemInfo; +import com.android.launcher3.LauncherAppState; import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.icons.LauncherIcons; +import com.android.launcher3.icons.IconCache; import com.android.launcher3.notification.NotificationInfo; import com.android.launcher3.notification.NotificationKeyData; import com.android.launcher3.notification.NotificationListener; @@ -153,13 +154,11 @@ public class PopupPopulator { String shortcutIdToDeDupe = notificationKeys.isEmpty() ? null : notificationKeys.get(0).shortcutId; shortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts, shortcutIdToDeDupe); + IconCache cache = LauncherAppState.getInstance(launcher).getIconCache(); for (int i = 0; i < shortcuts.size() && i < shortcutViews.size(); i++) { final ShortcutInfo shortcut = shortcuts.get(i); final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, launcher); - // Use unbadged icon for the menu. - LauncherIcons li = LauncherIcons.obtain(launcher); - si.bitmap = li.createShortcutIcon(shortcut, false /* badged */); - li.recycle(); + cache.getUnbadgedShortcutIcon(si, shortcut); si.rank = i; final DeepShortcutView view = shortcutViews.get(i); diff --git a/src/com/android/launcher3/util/ShortcutUtil.java b/src/com/android/launcher3/util/ShortcutUtil.java index a03b743233..49c97daf35 100644 --- a/src/com/android/launcher3/util/ShortcutUtil.java +++ b/src/com/android/launcher3/util/ShortcutUtil.java @@ -15,19 +15,10 @@ */ package com.android.launcher3.util; -import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; - -import android.content.Context; -import android.content.pm.ShortcutInfo; - -import androidx.annotation.NonNull; - import com.android.launcher3.ItemInfo; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.shortcuts.ShortcutKey; @@ -70,21 +61,6 @@ public class ShortcutUtil { && info instanceof WorkspaceItemInfo; } - /** - * Fetch the shortcut icon in background, then update the UI. - */ - public static void fetchAndUpdateShortcutIconAsync( - @NonNull Context context, @NonNull WorkspaceItemInfo info, @NonNull ShortcutInfo si, - boolean badged) { - MODEL_EXECUTOR.execute(() -> { - try (LauncherIcons li = LauncherIcons.obtain(context)) { - info.bitmap = li.createShortcutIcon(si, badged, null); - LauncherAppState.getInstance(context).getModel() - .updateAndBindWorkspaceItem(info, si); - } - }); - } - private static boolean isActive(ItemInfo info) { boolean isLoading = info instanceof WorkspaceItemInfo && ((WorkspaceItemInfo) info).hasPromiseIconUi(); diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java index 22c087453a..5ebf8d397f 100644 --- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java +++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java @@ -21,7 +21,7 @@ import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.Utilities; import com.android.launcher3.compat.AlphabeticIndexCompat; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.icons.ComponentWithLabel; +import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.icons.IconCache; import com.android.launcher3.pm.ShortcutConfigActivityInfo; import com.android.launcher3.util.MultiHashMap; @@ -85,12 +85,13 @@ public class WidgetsModel { * @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise * only widgets and shortcuts associated with the package/user are. */ - public List update(LauncherAppState app, @Nullable PackageUserKey packageUser) { + public List update( + LauncherAppState app, @Nullable PackageUserKey packageUser) { Preconditions.assertWorkerThread(); Context context = app.getContext(); final ArrayList widgetsAndShortcuts = new ArrayList<>(); - List updatedItems = new ArrayList<>(); + List updatedItems = new ArrayList<>(); try { InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); PackageManager pm = app.getContext().getPackageManager(); From 04fca1642ce859bb0f6b7fc7a806f469e6390303 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 5 Feb 2020 15:06:52 -0800 Subject: [PATCH 07/51] Separate 2-button mode check from ENABLE_OVERVIEW_ACTIONS This will allow us to cleanly remove ENABLE_OVERVIEW_ACTIONS while still keeping the shelf instead of actions in 2-button mode. Bug: 143361609 Change-Id: I5cd43b6d3daeb527c7787b1cb81fae9179d8911c --- .../uioverrides/states/OverviewState.java | 7 ++++-- .../android/quickstep/views/RecentsView.java | 2 +- .../com/android/quickstep/views/TaskView.java | 16 ++++++------ .../launcher3/BaseQuickstepLauncher.java | 12 +++++++++ .../QuickstepProcessInitializer.java | 25 ++----------------- .../quickstep/SysUINavigationMode.java | 6 +++++ .../android/quickstep/util/LayoutUtils.java | 15 +++++------ .../quickstep/views/ShelfScrimView.java | 3 ++- src/com/android/launcher3/Launcher.java | 7 +----- src/com/android/launcher3/LauncherState.java | 11 ++++++-- 10 files changed, 55 insertions(+), 49 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java index 644cfcb3a5..a1c837861d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -33,6 +33,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; +import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import android.graphics.Rect; import android.view.View; @@ -125,7 +126,8 @@ public class OverviewState extends LauncherState { @Override public ScaleAndTranslation getQsbScaleAndTranslation(Launcher launcher) { - if (this == OVERVIEW && ENABLE_OVERVIEW_ACTIONS.get()) { + if (this == OVERVIEW && ENABLE_OVERVIEW_ACTIONS.get() + && removeShelfFromOverview(launcher)) { // Treat the QSB as part of the hotseat so they move together. return getHotseatScaleAndTranslation(launcher); } @@ -158,7 +160,7 @@ public class OverviewState extends LauncherState { if (launcher.getDeviceProfile().isVerticalBarLayout()) { return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON; } else { - if (ENABLE_OVERVIEW_ACTIONS.get()) { + if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher)) { return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON; } @@ -229,6 +231,7 @@ public class OverviewState extends LauncherState { builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2); builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2); Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get() + && removeShelfFromOverview(launcher) ? OVERSHOOT_1_2 : OVERSHOOT_1_7; builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index c1ea533b2d..aaba308c0e 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -346,7 +346,7 @@ public abstract class RecentsView extends PagedView impl setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); mTaskTopMargin = getResources() .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin); - mTaskBottomMargin = LayoutUtils.thumbnailBottomMargin(getResources()); + mTaskBottomMargin = LayoutUtils.thumbnailBottomMargin(context); mSquaredTouchSlop = squaredTouchSlop(context); mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index 5954b86446..294bb7b564 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -22,6 +22,7 @@ import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LA import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; +import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -30,7 +31,6 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.app.ActivityOptions; import android.content.Context; -import android.content.res.Resources; import android.graphics.Outline; import android.graphics.Rect; import android.graphics.RectF; @@ -221,7 +221,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mCurrentFullscreenParams = new FullscreenDrawParams(mCornerRadius); mDigitalWellBeingToast = new DigitalWellBeingToast(mActivity, this); - mOutlineProvider = new TaskOutlineProvider(getResources(), mCurrentFullscreenParams); + mOutlineProvider = new TaskOutlineProvider(getContext(), mCurrentFullscreenParams); setOutlineProvider(mOutlineProvider); } @@ -230,13 +230,14 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { super.onFinishInflate(); mSnapshotView = findViewById(R.id.snapshot); mIconView = findViewById(R.id.icon); + final Context context = getContext(); TaskView.LayoutParams thumbnailParams = (LayoutParams) mSnapshotView.getLayoutParams(); - thumbnailParams.bottomMargin = LayoutUtils.thumbnailBottomMargin(getResources()); + thumbnailParams.bottomMargin = LayoutUtils.thumbnailBottomMargin(context); mSnapshotView.setLayoutParams(thumbnailParams); - if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) { + if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) { mActionsView = mSnapshotView.getTaskOverlay().getActionsView(); if (mActionsView != null) { TaskView.LayoutParams params = new TaskView.LayoutParams(LayoutParams.MATCH_PARENT, @@ -679,9 +680,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private final int mMarginBottom; private FullscreenDrawParams mFullscreenParams; - TaskOutlineProvider(Resources res, FullscreenDrawParams fullscreenParams) { - mMarginTop = res.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin); - mMarginBottom = LayoutUtils.thumbnailBottomMargin(res); + TaskOutlineProvider(Context context, FullscreenDrawParams fullscreenParams) { + mMarginTop = context.getResources().getDimensionPixelSize( + R.dimen.task_thumbnail_top_margin); + mMarginBottom = LayoutUtils.thumbnailBottomMargin(context); mFullscreenParams = fullscreenParams; } diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index ee53386f50..94ff63b5f7 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -25,6 +25,7 @@ import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_COUNT; import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN; import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_COUNT; import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN; +import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import android.animation.AnimatorSet; import android.animation.ValueAnimator; @@ -35,6 +36,7 @@ import android.os.CancellationSignal; import com.android.launcher3.LauncherState.ScaleAndTranslation; import com.android.launcher3.LauncherStateManager.StateHandler; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.WellbeingModel; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.proxy.ProxyActivityStarter; @@ -186,6 +188,16 @@ public abstract class BaseQuickstepLauncher extends Launcher } } + @Override + protected void setupViews() { + super.setupViews(); + + if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(this)) { + // Overview is above all other launcher elements, including qsb, so move it to the top. + getOverviewPanel().bringToFront(); + } + } + @Override protected StateHandler[] createStateHandlers() { return new StateHandler[] { diff --git a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java index 9817e32ae9..32268a49b5 100644 --- a/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java +++ b/quickstep/src/com/android/quickstep/QuickstepProcessInitializer.java @@ -15,11 +15,6 @@ */ package com.android.quickstep; -import static android.content.Context.MODE_PRIVATE; - -import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; -import static com.android.launcher3.config.FeatureFlags.FLAGS_PREF_NAME; - import android.content.Context; import android.content.pm.PackageManager; import android.os.UserManager; @@ -27,7 +22,6 @@ import android.util.Log; import com.android.launcher3.BuildConfig; import com.android.launcher3.MainProcessInitializer; -import com.android.launcher3.config.FeatureFlags; import com.android.systemui.shared.system.ThreadedRendererCompat; @SuppressWarnings("unused") @@ -55,22 +49,7 @@ public class QuickstepProcessInitializer extends MainProcessInitializer { super.init(context); // Elevate GPU priority for Quickstep and Remote animations. - ThreadedRendererCompat.setContextPriority(ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG); - - // Force disable some feature flags based on the system ui navigation mode. - SysUINavigationMode.Mode currMode = SysUINavigationMode.INSTANCE.get(context) - .addModeChangeListener(mode -> disableFeatureFlagsForSysuiNavMode(context, mode)); - disableFeatureFlagsForSysuiNavMode(context, currMode); - } - - private void disableFeatureFlagsForSysuiNavMode(Context ctx, SysUINavigationMode.Mode mode) { - if (mode == SysUINavigationMode.Mode.TWO_BUTTONS) { - ctx.getSharedPreferences(FLAGS_PREF_NAME, MODE_PRIVATE) - .edit() - .putBoolean(ENABLE_OVERVIEW_ACTIONS.key, false) - .apply(); - - FeatureFlags.initialize(ctx); - } + ThreadedRendererCompat.setContextPriority( + ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG); } } diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java index 388b323a50..375e589603 100644 --- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java +++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java @@ -122,6 +122,12 @@ public class SysUINavigationMode { } } + /** @return Whether we can remove the shelf from overview. */ + public static boolean removeShelfFromOverview(Context context) { + // The shelf is core to the two-button mode model, so we need to continue supporting it. + return getMode(context) != Mode.TWO_BUTTONS; + } + public interface NavigationModeChangeListener { void onNavigationModeChanged(Mode newMode); diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java index b249f48389..9cf55b3e76 100644 --- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java +++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java @@ -16,6 +16,7 @@ package com.android.quickstep.util; import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS; +import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -59,7 +60,7 @@ public class LayoutUtils { } else { Resources res = context.getResources(); - if (ENABLE_OVERVIEW_ACTIONS.get()) { + if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) { //TODO: this needs to account for the swipe gesture height and accessibility // UI when shown. extraSpace = 0; @@ -112,7 +113,7 @@ public class LayoutUtils { final int paddingResId; if (dp.isVerticalBarLayout()) { paddingResId = R.dimen.landscape_task_card_horz_space; - } else if (ENABLE_OVERVIEW_ACTIONS.get()) { + } else if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) { paddingResId = R.dimen.portrait_task_card_horz_space_big_overview; } else { paddingResId = R.dimen.portrait_task_card_horz_space; @@ -121,7 +122,7 @@ public class LayoutUtils { } float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin); - float bottomMargin = thumbnailBottomMargin(res); + float bottomMargin = thumbnailBottomMargin(context); float paddingVert = res.getDimension(R.dimen.task_card_vert_space); // Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless @@ -147,7 +148,7 @@ public class LayoutUtils { public static int getShelfTrackingDistance(Context context, DeviceProfile dp) { // Track the bottom of the window. - if (ENABLE_OVERVIEW_ACTIONS.get()) { + if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) { Rect taskSize = new Rect(); calculateLauncherTaskSize(context, dp, taskSize); return (dp.heightPx - taskSize.height()) / 2; @@ -162,9 +163,9 @@ public class LayoutUtils { * Get the margin that the task thumbnail view should use. * @return the margin in pixels. */ - public static int thumbnailBottomMargin(Resources resources) { - if (ENABLE_OVERVIEW_ACTIONS.get()) { - return resources.getDimensionPixelSize(R.dimen.overview_actions_height); + public static int thumbnailBottomMargin(Context context) { + if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) { + return context.getResources().getDimensionPixelSize(R.dimen.overview_actions_height); } else { return 0; } diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java index 7ed1e21dfb..1ce3549f39 100644 --- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -160,7 +160,8 @@ public class ShelfScrimView extends ScrimView Context context = getContext(); if ((OVERVIEW.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) == 0) { mDragHandleProgress = 1; - if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) { + if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() + && SysUINavigationMode.removeShelfFromOverview(context)) { // Fade in all apps background quickly to distinguish from swiping from nav bar. mMidAlpha = Themes.getAttrInteger(context, R.attr.allAppsInterimScrimAlpha); mMidProgress = OverviewState.getDefaultVerticalProgress(mLauncher); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 43540cec72..d2506588e1 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1138,7 +1138,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, /** * Finds all the views we need and configure them properly. */ - private void setupViews() { + protected void setupViews() { mDragLayer = findViewById(R.id.drag_layer); mFocusHandler = mDragLayer.getFocusIndicatorHelper(); mWorkspace = mDragLayer.findViewById(R.id.workspace); @@ -1174,11 +1174,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mDropTargetBar.setup(mDragController); mAllAppsController.setupViews(mAppsView); - - if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) { - // Overview is above all other launcher elements, including qsb, so move it to the top. - mOverviewPanel.bringToFront(); - } } /** diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 7e06099451..16be391891 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -41,8 +41,10 @@ import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL; +import android.view.View; import android.view.animation.Interpolator; +import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.states.HintState; import com.android.launcher3.states.SpringLoadedState; @@ -337,8 +339,13 @@ public abstract class LauncherState { hotseat.setScaleX(0.92f); hotseat.setScaleY(0.92f); if (ENABLE_OVERVIEW_ACTIONS.get()) { - launcher.getAppsView().setScaleX(0.92f); - launcher.getAppsView().setScaleY(0.92f); + AllAppsContainerView qsbContainer = launcher.getAppsView(); + View qsb = qsbContainer.getSearchView(); + boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0; + if (!qsbVisible) { + qsbContainer.setScaleX(0.92f); + qsbContainer.setScaleY(0.92f); + } } } } else if (this == NORMAL && fromState == OVERVIEW_PEEK) { From ec9c109c46a5558ba0bf3391b25cc3bdf72f1640 Mon Sep 17 00:00:00 2001 From: vadimt Date: Thu, 6 Feb 2020 15:12:39 -0800 Subject: [PATCH 08/51] Attempt to workaround navigation mode mismatch errors Assuming that the nav mode state needs to "settle", adding waiting for this. This might be a temporary solution. Bug: 149024111 Change-Id: Ifbd874546a4cb6b07ad3d3825c95d19bc5836b38 --- .../com/android/launcher3/tapl/LauncherInstrumentation.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 40898970c3..42861e797b 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -489,6 +489,12 @@ public final class LauncherInstrumentation { assertEquals("Unexpected display rotation", mExpectedRotation, mDevice.getDisplayRotation()); + // b/149024111 + for (int i = 0; i != 100; ++i) { + if (getNavigationModeMismatchError() == null) break; + sleep(100); + } + final String error = getNavigationModeMismatchError(); assertTrue(error, error == null); log("verifyContainerType: " + containerType); From a16ce7ea6ae852e5dd4d819843ab63fd9a6ebe52 Mon Sep 17 00:00:00 2001 From: Chihhang Chuang Date: Fri, 7 Feb 2020 17:38:20 +0800 Subject: [PATCH 09/51] Fix build break from generating robo test code coverage Use absolute path for LOCAL_INSTRUMENT_SOURCE_DIRS, because Jacoco fail to get the source code path to parse the code coverage. Test step: 1. tapas RunLauncherRoboTests 2. make -j30 dist (Make sure RunLauncherRoboTests does not break) 3. make -j30 RunLauncherRoboTests-jacoco dist 4. See the coverage report Bug: 149001617 Change-Id: If82a839ae52c20c7eb269090976de05fa5d462c4 --- robolectric_tests/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robolectric_tests/Android.mk b/robolectric_tests/Android.mk index 60599819e1..7c7e73c374 100644 --- a/robolectric_tests/Android.mk +++ b/robolectric_tests/Android.mk @@ -52,7 +52,7 @@ LOCAL_JAVA_LIBRARIES := LauncherRoboTests LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_TEST_PACKAGE := Launcher3 -LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src +LOCAL_INSTRUMENT_SOURCE_DIRS := packages/apps/Launcher3/src LOCAL_ROBOTEST_TIMEOUT := 36000 From c71db9874718b6ed3bb497d543c119fbe2993c52 Mon Sep 17 00:00:00 2001 From: vadimt Date: Fri, 7 Feb 2020 10:34:59 -0800 Subject: [PATCH 10/51] Increasing nav mode settlement timeout as an attempt to workaround nav mode mismatch bug. Bug: 148422894 Change-Id: I1295c1415a308ec461d302c9973309f4de77f984 --- .../src/com/android/quickstep/NavigationModeSwitchRule.java | 3 ++- .../com/android/launcher3/tapl/LauncherInstrumentation.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index 97424bb8f9..1229a637b4 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -197,7 +197,8 @@ public class NavigationModeSwitchRule implements TestRule { Wait.atMost(() -> "Switching nav mode: " + launcher.getNavigationModeMismatchError(), - () -> launcher.getNavigationModeMismatchError() == null, WAIT_TIME_MS, launcher); + () -> launcher.getNavigationModeMismatchError() == null, + 60000 /* b/148422894 */, launcher); return true; } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 5eb164ecd4..ebf48a21f7 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -490,8 +490,8 @@ public final class LauncherInstrumentation { assertEquals("Unexpected display rotation", mExpectedRotation, mDevice.getDisplayRotation()); - // b/149024111 - for (int i = 0; i != 100; ++i) { + // b/148422894 + for (int i = 0; i != 600; ++i) { if (getNavigationModeMismatchError() == null) break; sleep(100); } From d633c9c7da87d6eab96d72c5f6480d6e9eb27c6a Mon Sep 17 00:00:00 2001 From: vadimt Date: Wed, 22 Jan 2020 18:00:37 -0800 Subject: [PATCH 11/51] Verifying events from TouchInteractionService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a guaranteed order in which TIS events will be registered relative to other TIS events. However, relative to the touch events arriving to the activity, TIS events can come in any order. Now the event checker verifies 2 independent ordered event sequences: from TIS, and “the rest” (Main). Change-Id: I5872e0e3b0b498050a91c67105fbe4a29411375a --- .../quickstep/TouchInteractionService.java | 8 +- .../inputconsumers/DelegateInputConsumer.java | 3 +- .../DeviceLockedInputConsumer.java | 3 +- .../OtherActivityInputConsumer.java | 3 +- .../inputconsumers/OverviewInputConsumer.java | 3 +- .../OverviewWithoutFocusInputConsumer.java | 3 +- .../com/android/quickstep/views/TaskView.java | 6 +- src/com/android/launcher3/BaseActivity.java | 5 +- .../launcher3/BaseDraggingActivity.java | 5 +- src/com/android/launcher3/Launcher.java | 8 +- .../launcher3/testing/TestLogging.java | 21 +- .../launcher3/testing/TestProtocol.java | 2 + .../launcher3/tapl/AddToHomeScreenPrompt.java | 9 + .../com/android/launcher3/tapl/AppIcon.java | 4 +- .../launcher3/tapl/AppIconMenuItem.java | 4 +- .../android/launcher3/tapl/Background.java | 8 +- .../tapl/LauncherInstrumentation.java | 194 +++++++++++++----- .../android/launcher3/tapl/OverviewTask.java | 4 +- .../com/android/launcher3/tapl/Workspace.java | 4 +- 19 files changed, 218 insertions(+), 79 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index edaef30a8e..693f22347f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -145,7 +145,7 @@ public class TouchInteractionService extends Service implements PluginListener ActiveGestureLog.INSTANCE.addLog("startQuickstep"); } if (mInputMonitor != null) { - TestLogging.recordEvent("pilferPointers"); + TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "pilferPointers"); mInputMonitor.pilferPointers(); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java index 6bfc3fd6b9..823b254d80 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java @@ -23,6 +23,7 @@ import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.logging.StatsLogUtils; import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.quickstep.GestureState; @@ -64,7 +65,7 @@ public class OverviewWithoutFocusInputConsumer implements InputConsumer { private void onInterceptTouch() { if (mInputMonitor != null) { - TestLogging.recordEvent("pilferPointers"); + TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "pilferPointers"); mInputMonitor.pilferPointers(); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index 294bb7b564..8b7ce10b2b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -58,6 +58,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; @@ -334,9 +335,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { Consumer resultCallback, Handler resultCallbackHandler) { if (mTask != null) { final ActivityOptions opts; - if (Utilities.IS_RUNNING_IN_TEST_HARNESS) { - TestLogging.recordEvent("startActivityFromRecentsAsync:" + mTask); - } + TestLogging.recordEvent( + TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask); if (animate) { opts = mActivity.getActivityLaunchOptions(this); if (freezeTaskList) { diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index f3c5191bbe..217a41c083 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -42,6 +42,7 @@ import com.android.launcher3.logging.StatsLogUtils.LogStateProvider; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.logging.UserEventDispatcher.UserEventDelegate; import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.ViewCache; @@ -330,9 +331,7 @@ public abstract class BaseActivity extends Activity return; } try { - if (Utilities.IS_RUNNING_IN_TEST_HARNESS) { - TestLogging.recordEvent("start: shortcut: " + packageName); - } + TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: shortcut", packageName); getSystemService(LauncherApps.class).startShortcut(packageName, id, sourceBounds, startActivityOptions, user); } catch (SecurityException | IllegalStateException e) { diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index dda38b308d..8d4af11dcc 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -37,6 +37,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.testing.TestLogging; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.uioverrides.DisplayRotationListener; import com.android.launcher3.uioverrides.WallpaperColorInfo; @@ -167,9 +168,7 @@ public abstract class BaseDraggingActivity extends BaseActivity startShortcutIntentSafely(intent, optsBundle, item, sourceContainer); } else if (user == null || user.equals(Process.myUserHandle())) { // Could be launching some bookkeeping activity - if (Utilities.IS_RUNNING_IN_TEST_HARNESS) { - TestLogging.recordEvent("start: activity: " + intent); - } + TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: activity", intent); startActivity(intent, optsBundle); AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(), Process.myUserHandle(), sourceContainer); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index d2506588e1..a53805ffad 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1778,17 +1778,13 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override public boolean dispatchKeyEvent(KeyEvent event) { - if (Utilities.IS_RUNNING_IN_TEST_HARNESS) { - TestLogging.recordEvent("Key event: " + event); - } + TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Key event", event); return (event.getKeyCode() == KeyEvent.KEYCODE_HOME) || super.dispatchKeyEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { - if (Utilities.IS_RUNNING_IN_TEST_HARNESS && ev.getAction() != MotionEvent.ACTION_MOVE) { - TestLogging.recordEvent("Touch event: " + ev); - } + TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev); return super.dispatchTouchEvent(ev); } diff --git a/src/com/android/launcher3/testing/TestLogging.java b/src/com/android/launcher3/testing/TestLogging.java index fd066c1ce1..d522d81665 100644 --- a/src/com/android/launcher3/testing/TestLogging.java +++ b/src/com/android/launcher3/testing/TestLogging.java @@ -17,13 +17,30 @@ package com.android.launcher3.testing; import android.util.Log; +import android.view.MotionEvent; import com.android.launcher3.Utilities; public final class TestLogging { - public static void recordEvent(String event) { + private static void recordEventSlow(String sequence, String event) { + Log.d(TestProtocol.TAPL_EVENTS_TAG, sequence + " / " + event); + } + + public static void recordEvent(String sequence, String event) { if (Utilities.IS_RUNNING_IN_TEST_HARNESS) { - Log.d(TestProtocol.TAPL_EVENTS_TAG, event); + recordEventSlow(sequence, event); + } + } + + public static void recordEvent(String sequence, String message, Object parameter) { + if (Utilities.IS_RUNNING_IN_TEST_HARNESS) { + recordEventSlow(sequence, message + ": " + parameter); + } + } + + public static void recordMotionEvent(String sequence, String message, MotionEvent event) { + if (Utilities.IS_RUNNING_IN_TEST_HARNESS && event.getAction() != MotionEvent.ACTION_MOVE) { + recordEventSlow(sequence, message + ": " + event); } } } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index 2f053c99e8..35a7f3e622 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -33,6 +33,8 @@ public final class TestProtocol { public static final int BACKGROUND_APP_STATE_ORDINAL = 6; public static final int HINT_STATE_ORDINAL = 7; public static final String TAPL_EVENTS_TAG = "TaplEvents"; + public static final String SEQUENCE_MAIN = "Main"; + public static final String SEQUENCE_TIS = "TIS"; public static String stateOrdinalToString(int ordinal) { switch (ordinal) { diff --git a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java index afb50e06f3..468f54c0d9 100644 --- a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java +++ b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java @@ -21,6 +21,8 @@ import static java.util.regex.Pattern.CASE_INSENSITIVE; import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiObject2; +import com.android.launcher3.testing.TestProtocol; + import java.util.regex.Pattern; public class AddToHomeScreenPrompt { @@ -38,6 +40,13 @@ public class AddToHomeScreenPrompt { public void addAutomatically() { try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) { + if (mLauncher.getNavigationModel() + != LauncherInstrumentation.NavigationModel.THREE_BUTTON) { + mLauncher.expectEvent( + TestProtocol.SEQUENCE_TIS, LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS); + mLauncher.expectEvent( + TestProtocol.SEQUENCE_TIS, LauncherInstrumentation.EVENT_TOUCH_UP_TIS); + } mLauncher.waitForObjectInContainer( mWidgetCell.getParent().getParent().getParent().getParent(), By.text(ADD_AUTOMATICALLY)).click(); diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java index 3f814fd1eb..8932291f94 100644 --- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java +++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java @@ -22,6 +22,8 @@ import androidx.test.uiautomator.By; import androidx.test.uiautomator.BySelector; import androidx.test.uiautomator.UiObject2; +import com.android.launcher3.testing.TestProtocol; + import java.util.regex.Pattern; /** @@ -56,6 +58,6 @@ public final class AppIcon extends Launchable { @Override protected void expectActivityStartEvents() { - mLauncher.expectEvent(START_EVENT); + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, START_EVENT); } } diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java index fadfd9ff38..f8dd89c60c 100644 --- a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java +++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java @@ -18,6 +18,8 @@ package com.android.launcher3.tapl; import androidx.test.uiautomator.UiObject2; +import com.android.launcher3.testing.TestProtocol; + import java.util.regex.Pattern; /** @@ -45,6 +47,6 @@ public class AppIconMenuItem extends Launchable { @Override protected void expectActivityStartEvents() { - mLauncher.expectEvent(START_SHORTCUT_EVENT); + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, START_SHORTCUT_EVENT); } } diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java index 9f29a1a826..2acab97454 100644 --- a/tests/tapl/com/android/launcher3/tapl/Background.java +++ b/tests/tapl/com/android/launcher3/tapl/Background.java @@ -131,7 +131,7 @@ public class Background extends LauncherInstrumentation.VisibleContainer { } case THREE_BUTTON: - mLauncher.expectEvent(SQUARE_BUTTON_EVENT); + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT); mLauncher.runToState( () -> mLauncher.waitForSystemUiObject("recent_apps").click(), OVERVIEW_STATE_ORDINAL); @@ -195,14 +195,14 @@ public class Background extends LauncherInstrumentation.VisibleContainer { case THREE_BUTTON: // Double press the recents button. UiObject2 recentsButton = mLauncher.waitForSystemUiObject("recent_apps"); - mLauncher.expectEvent(SQUARE_BUTTON_EVENT); + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT); mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL); mLauncher.getOverview(); - mLauncher.expectEvent(SQUARE_BUTTON_EVENT); + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT); recentsButton.click(); break; } - mLauncher.expectEvent(TASK_START_EVENT); + mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT); } protected String getSwipeHeightRequestName() { diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 5eb164ecd4..8d98cef867 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -75,8 +75,10 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Deque; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; import java.util.function.Function; @@ -101,13 +103,17 @@ public final class LauncherInstrumentation { static final Pattern EVENT_LOG_ENTRY = Pattern.compile( "(?