Adds restore metrics to RestoreDbTask.java
Bug: 307527314 Flag: ACONFIG enable_launcher_br_metrics TEAMFOOD Test: locally verified Change-Id: I105b17276cf7e2c270c819854a8fbc269b7c81b4
This commit is contained in:
@@ -22,6 +22,8 @@ open class LauncherRestoreEventLogger : ResourceBasedOverride {
|
||||
const val RESTORE_ERROR_SHORTCUT_NOT_FOUND = "shortcut_not_found"
|
||||
const val RESTORE_ERROR_APP_NOT_INSTALLED = "app_not_installed"
|
||||
const val RESTORE_ERROR_WIDGETS_DISABLED = "widgets_disabled"
|
||||
const val RESTORE_ERROR_PROFILE_NOT_RESTORED = "profile_not_restored"
|
||||
const val RESTORE_ERROR_WIDGET_REMOVED = "widget_not_found"
|
||||
|
||||
fun newInstance(context: Context?): LauncherRestoreEventLogger {
|
||||
return ResourceBasedOverride.Overrides.getObject(
|
||||
|
||||
@@ -18,12 +18,18 @@ package com.android.launcher3.provider;
|
||||
|
||||
import static android.os.Process.myUserHandle;
|
||||
|
||||
import static com.android.launcher3.Flags.enableLauncherBrMetrics;
|
||||
import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
|
||||
import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
|
||||
import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE;
|
||||
import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
|
||||
import static com.android.launcher3.LauncherPrefs.RESTORE_DEVICE;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
|
||||
import static com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RESTORE_ERROR_PROFILE_NOT_RESTORED;
|
||||
import static com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RESTORE_ERROR_WIDGETS_DISABLED;
|
||||
import static com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RESTORE_ERROR_WIDGET_REMOVED;
|
||||
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
|
||||
import static com.android.launcher3.widget.LauncherWidgetHolder.APPWIDGET_HOST_ID;
|
||||
|
||||
@@ -53,6 +59,7 @@ import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.model.DeviceGridState;
|
||||
import com.android.launcher3.model.LoaderTask;
|
||||
@@ -123,8 +130,11 @@ public class RestoreDbTask {
|
||||
FileLog.d(TAG, "performRestore: starting restore from db");
|
||||
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
|
||||
RestoreDbTask task = new RestoreDbTask();
|
||||
task.sanitizeDB(context, controller, db, new BackupManager(context));
|
||||
task.restoreAppWidgetIdsIfExists(context, controller);
|
||||
BackupManager backupManager = new BackupManager(context);
|
||||
LauncherRestoreEventLogger restoreEventLogger =
|
||||
LauncherRestoreEventLogger.Companion.newInstance(context);
|
||||
task.sanitizeDB(context, controller, db, backupManager, restoreEventLogger);
|
||||
task.restoreAppWidgetIdsIfExists(context, controller, restoreEventLogger);
|
||||
t.commit();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
@@ -147,7 +157,8 @@ public class RestoreDbTask {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected int sanitizeDB(Context context, ModelDbController controller, SQLiteDatabase db,
|
||||
BackupManager backupManager) throws Exception {
|
||||
BackupManager backupManager, LauncherRestoreEventLogger restoreEventLogger)
|
||||
throws Exception {
|
||||
logFavoritesTable(db, "Old Launcher Database before sanitizing:", null, null);
|
||||
// Primary user ids
|
||||
long myProfileId = controller.getSerialNumberForUser(myUserHandle());
|
||||
@@ -186,6 +197,9 @@ public class RestoreDbTask {
|
||||
Arrays.fill(args, "?");
|
||||
final String where = "profileId NOT IN (" + TextUtils.join(", ", Arrays.asList(args)) + ")";
|
||||
logFavoritesTable(db, "items to delete from unrestored profiles:", where, profileIds);
|
||||
if (enableLauncherBrMetrics()) {
|
||||
reportUnrestoredProfiles(db, where, profileIds, restoreEventLogger);
|
||||
}
|
||||
int itemsDeletedCount = db.delete(Favorites.TABLE_NAME, where, profileIds);
|
||||
FileLog.d(TAG, itemsDeletedCount + " total items from unrestored user(s) were deleted");
|
||||
|
||||
@@ -345,21 +359,24 @@ public class RestoreDbTask {
|
||||
DeviceGridState deviceGridState = new DeviceGridState(context);
|
||||
FileLog.d(TAG, "restore initiated from backup: DeviceGridState=" + deviceGridState);
|
||||
LauncherPrefs.get(context).putSync(RESTORE_DEVICE.to(deviceGridState.getDeviceType()));
|
||||
LauncherPrefs.get(context).putSync(IS_FIRST_LOAD_AFTER_RESTORE.to(true));
|
||||
if (enableLauncherBrMetrics()) {
|
||||
LauncherPrefs.get(context).putSync(IS_FIRST_LOAD_AFTER_RESTORE.to(true));
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@VisibleForTesting
|
||||
void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller) {
|
||||
void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller,
|
||||
LauncherRestoreEventLogger restoreEventLogger) {
|
||||
LauncherPrefs lp = LauncherPrefs.get(context);
|
||||
if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
|
||||
AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID);
|
||||
restoreAppWidgetIds(context, controller,
|
||||
restoreAppWidgetIds(context, controller, restoreEventLogger,
|
||||
IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
|
||||
IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
|
||||
host);
|
||||
} else {
|
||||
FileLog.d(TAG, "No app widget ids were received from backup to restore.");
|
||||
FileLog.d(TAG, "Did not receive new app widget id map during Launcher restore");
|
||||
}
|
||||
|
||||
lp.remove(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS);
|
||||
@@ -370,10 +387,13 @@ public class RestoreDbTask {
|
||||
*/
|
||||
@WorkerThread
|
||||
private void restoreAppWidgetIds(Context context, ModelDbController controller,
|
||||
int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
|
||||
LauncherRestoreEventLogger launcherRestoreEventLogger, int[] oldWidgetIds,
|
||||
int[] newWidgetIds, @NonNull AppWidgetHost host) {
|
||||
if (WidgetsModel.GO_DISABLE_WIDGETS) {
|
||||
FileLog.e(TAG, "Skipping widget ID remap as widgets not supported");
|
||||
host.deleteHost();
|
||||
launcherRestoreEventLogger.logFavoritesItemsRestoreFailed(Favorites.ITEM_TYPE_APPWIDGET,
|
||||
oldWidgetIds.length, RESTORE_ERROR_WIDGETS_DISABLED);
|
||||
return;
|
||||
}
|
||||
if (!RestoreDbTask.isPending(context)) {
|
||||
@@ -437,11 +457,16 @@ public class RestoreDbTask {
|
||||
FileLog.d(TAG, "Deleting widgetId: " + newWidgetIds[i] + " with old id: "
|
||||
+ oldWidgetId);
|
||||
host.deleteAppWidgetId(newWidgetIds[i]);
|
||||
launcherRestoreEventLogger.logSingleFavoritesItemRestoreFailed(
|
||||
ITEM_TYPE_APPWIDGET,
|
||||
RESTORE_ERROR_WIDGET_REMOVED
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logFavoritesTable(controller.getDb(), "launcher db after remap widget ids", null, null);
|
||||
LauncherAppState app = LauncherAppState.getInstanceNoCreate();
|
||||
if (app != null) {
|
||||
app.getModel().forceReload();
|
||||
@@ -476,17 +501,16 @@ public class RestoreDbTask {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
for (int i = 0; i < widgetIdList.size(); i++) {
|
||||
builder.append("[")
|
||||
builder.append("[appWidgetId=")
|
||||
.append(widgetIdList.get(i))
|
||||
.append(", ")
|
||||
.append(", restoreFlag=")
|
||||
.append(widgetRestoreList.get(i))
|
||||
.append(", ")
|
||||
.append(", profileId=")
|
||||
.append(widgetProfileIdList.get(i))
|
||||
.append("]");
|
||||
}
|
||||
builder.append("]");
|
||||
Log.d(TAG, "restoreAppWidgetIds: all widget ids in database: "
|
||||
+ builder);
|
||||
Log.d(TAG, "restoreAppWidgetIds: all widget ids in database: " + builder);
|
||||
} catch (Exception ex) {
|
||||
Log.e(TAG, "Getting widget ids from the database failed", ex);
|
||||
}
|
||||
@@ -545,7 +569,7 @@ public class RestoreDbTask {
|
||||
*/
|
||||
public static void logFavoritesTable(SQLiteDatabase database, @NonNull String logHeader,
|
||||
String where, String[] profileIds) {
|
||||
try (Cursor itemsToDelete = database.query(
|
||||
try (Cursor cursor = database.query(
|
||||
/* table */ Favorites.TABLE_NAME,
|
||||
/* columns */ DB_COLUMNS_TO_LOG,
|
||||
/* selection */ where,
|
||||
@@ -554,26 +578,53 @@ public class RestoreDbTask {
|
||||
/* having */ null,
|
||||
/* orderBy */ null
|
||||
)) {
|
||||
if (itemsToDelete.moveToFirst()) {
|
||||
String[] columnNames = itemsToDelete.getColumnNames();
|
||||
if (cursor.moveToFirst()) {
|
||||
String[] columnNames = cursor.getColumnNames();
|
||||
StringBuilder stringBuilder = new StringBuilder(logHeader + "\n");
|
||||
do {
|
||||
for (String columnName : columnNames) {
|
||||
stringBuilder.append(columnName)
|
||||
.append("=")
|
||||
.append(itemsToDelete.getString(
|
||||
itemsToDelete.getColumnIndex(columnName)))
|
||||
.append(cursor.getString(
|
||||
cursor.getColumnIndex(columnName)))
|
||||
.append(" ");
|
||||
}
|
||||
stringBuilder.append("\n");
|
||||
} while (itemsToDelete.moveToNext());
|
||||
} while (cursor.moveToNext());
|
||||
FileLog.d(TAG, stringBuilder.toString());
|
||||
} else {
|
||||
FileLog.d(TAG, "logFavoritesTable: No items found from query for"
|
||||
FileLog.d(TAG, "logFavoritesTable: No items found from query for "
|
||||
+ "\"" + logHeader + "\"");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(TAG, "logFavoritesTable: Error reading from database", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Queries and reports the count of each itemType to be removed due to unrestored profiles.
|
||||
* @param database The Launcher db to query from.
|
||||
* @param where Query being used for to find unrestored profiles
|
||||
* @param profileIds profile ids that were not restored
|
||||
* @param restoreEventLogger Backup/Restore Logger to report metrics
|
||||
*/
|
||||
private void reportUnrestoredProfiles(SQLiteDatabase database, String where,
|
||||
String[] profileIds, LauncherRestoreEventLogger restoreEventLogger) {
|
||||
final String query = "SELECT itemType, COUNT(*) AS count FROM favorites WHERE "
|
||||
+ where + " GROUP BY itemType";
|
||||
try (Cursor cursor = database.rawQuery(query, profileIds)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
restoreEventLogger.logFavoritesItemsRestoreFailed(
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(ITEM_TYPE)),
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow("count")),
|
||||
RESTORE_ERROR_PROFILE_NOT_RESTORED
|
||||
);
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(TAG, "reportUnrestoredProfiles: Error reading from database", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger;
|
||||
import com.android.launcher3.model.ModelDbController;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
@@ -90,6 +91,7 @@ public class RestoreDbTaskTest {
|
||||
private SQLiteDatabase mMockDb;
|
||||
private Cursor mMockCursor;
|
||||
private LauncherPrefs mPrefs;
|
||||
private LauncherRestoreEventLogger mMockRestoreEventLogger;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -100,6 +102,7 @@ public class RestoreDbTaskTest {
|
||||
mMockDb = mock(SQLiteDatabase.class);
|
||||
mMockCursor = mock(Cursor.class);
|
||||
mPrefs = new LauncherPrefs(mContext);
|
||||
mMockRestoreEventLogger = mock(LauncherRestoreEventLogger.class);
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -178,7 +181,7 @@ public class RestoreDbTaskTest {
|
||||
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
|
||||
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
|
||||
|
||||
mTask.sanitizeDB(mContext, controller, controller.getDb(), bm);
|
||||
mTask.sanitizeDB(mContext, controller, controller.getDb(), bm, mMockRestoreEventLogger);
|
||||
|
||||
// All the data has been migrated to the new user ids
|
||||
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
|
||||
@@ -207,7 +210,7 @@ public class RestoreDbTaskTest {
|
||||
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
|
||||
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
|
||||
|
||||
mTask.sanitizeDB(mContext, controller, controller.getDb(), bm);
|
||||
mTask.sanitizeDB(mContext, controller, controller.getDb(), bm, mMockRestoreEventLogger);
|
||||
|
||||
// All the data has been migrated to the new user ids
|
||||
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
|
||||
@@ -219,7 +222,7 @@ public class RestoreDbTaskTest {
|
||||
@Test
|
||||
public void givenLauncherPrefsHasNoIds_whenRestoreAppWidgetIdsIfExists_thenIdsAreRemoved() {
|
||||
// When
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController, mMockRestoreEventLogger);
|
||||
// Then
|
||||
assertThat(mPrefs.has(OLD_APP_WIDGET_IDS, APP_WIDGET_IDS)).isFalse();
|
||||
}
|
||||
@@ -235,7 +238,7 @@ public class RestoreDbTaskTest {
|
||||
|
||||
// When
|
||||
setRestoredAppWidgetIds(mContext, expectedOldIds, expectedNewIds);
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController, mMockRestoreEventLogger);
|
||||
|
||||
// Then
|
||||
assertThat(expectedHost.getAppWidgetIds()).isEqualTo(expectedOldIds);
|
||||
@@ -257,7 +260,7 @@ public class RestoreDbTaskTest {
|
||||
|
||||
// When
|
||||
setRestoredAppWidgetIds(mContext, expectedOldIds, expectedNewIds);
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController, mMockRestoreEventLogger);
|
||||
|
||||
// Then
|
||||
assertThat(expectedHost.getAppWidgetIds()).isEqualTo(expectedOldIds);
|
||||
@@ -280,12 +283,13 @@ public class RestoreDbTaskTest {
|
||||
when(mMockDb.query(any(), any(), any(), any(), any(), any(), any()))
|
||||
.thenReturn(mMockCursor);
|
||||
when(mMockCursor.moveToFirst()).thenReturn(true);
|
||||
when(mMockCursor.getColumnNames()).thenReturn(new String[] {});
|
||||
when(mMockCursor.isAfterLast()).thenReturn(true);
|
||||
RestoreDbTask.setPending(mContext);
|
||||
|
||||
// When
|
||||
setRestoredAppWidgetIds(mContext, expectedOldIds, expectedNewIds);
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController);
|
||||
mTask.restoreAppWidgetIdsIfExists(mContext, mMockController, mMockRestoreEventLogger);
|
||||
|
||||
// Then
|
||||
assertThat(expectedHost.getAppWidgetIds()).isEqualTo(allExpectedIds);
|
||||
|
||||
Reference in New Issue
Block a user