Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f667a135 authored by Samuel Fufa's avatar Samuel Fufa
Browse files

Restore hotseat when user turns off suggestions immediately after migration

- Creates a backup table `hybrid_hotseat_restore` and copies current workspace layout before hotseat migration
- restores to back up when user turns off suggestions and launcher receives empty predicted items
- deletes hybrid_hotseat_restore table if there's a layout change

Test: Manual
Bug: 157688471
Change-Id: Iaf7ddb33799493d36dbcd12408b57224162221d9
parent bc374cf7
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ public class HotseatEduController {

    private final Launcher mLauncher;
    private final Hotseat mHotseat;
    private final HotseatRestoreHelper mRestoreHelper;
    private List<WorkspaceItemInfo> mPredictedApps;
    private HotseatEduDialog mActiveDialog;

@@ -59,9 +60,10 @@ public class HotseatEduController {
    private IntArray mNewScreens = null;
    private Runnable mOnOnboardingComplete;

    HotseatEduController(Launcher launcher, Runnable runnable) {
    HotseatEduController(Launcher launcher, HotseatRestoreHelper restoreHelper, Runnable runnable) {
        mLauncher = launcher;
        mHotseat = launcher.getHotseat();
        mRestoreHelper = restoreHelper;
        mOnOnboardingComplete = runnable;
    }

@@ -69,11 +71,14 @@ public class HotseatEduController {
     * Checks what type of migration should be used and migrates hotseat
     */
    void migrate() {
        mRestoreHelper.createBackup();
        if (FeatureFlags.HOTSEAT_MIGRATE_TO_FOLDER.get()) {
            migrateToFolder();
        } else {
            migrateHotseatWhole();
        }
        Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_enabled, R.string.hotseat_turn_off,
                null, () -> mLauncher.startActivity(new Intent(SETTINGS_ACTION)));
    }

    /**
@@ -84,7 +89,6 @@ public class HotseatEduController {
     */
    private int migrateToFolder() {
        ArrayDeque<FolderInfo> folders = new ArrayDeque<>();

        ArrayList<WorkspaceItemInfo> putIntoFolder = new ArrayList<>();

        //separate folders and items that can get in folders
+2 −1
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@
package com.android.launcher3.hybridhotseat;

import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.HYBRID_HOTSEAT_CANCELED;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType
        .HYBRID_HOTSEAT_CANCELED;

import android.animation.PropertyValuesHolder;
import android.content.Context;
+8 −2
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@ public class HotseatPredictionController implements DragController.DragListener,
    private Launcher mLauncher;
    private final Hotseat mHotseat;

    private final HotseatRestoreHelper mRestoreHelper;

    private List<ComponentKeyMapper> mComponentKeyMappers = new ArrayList<>();

    private DynamicItemCache mDynamicItemCache;
@@ -129,6 +131,7 @@ public class HotseatPredictionController implements DragController.DragListener,
        mHotSeatItemsCount = mLauncher.getDeviceProfile().inv.numHotseatIcons;
        launcher.getDeviceProfile().inv.addOnChangeListener(this);
        mHotseat.addOnAttachStateChangeListener(this);
        mRestoreHelper = new HotseatRestoreHelper(mLauncher);
        if (mHotseat.isAttachedToWindow()) {
            onViewAttachedToWindow(mHotseat);
        }
@@ -297,7 +300,8 @@ public class HotseatPredictionController implements DragController.DragListener,
        });
        setPauseUIUpdate(false);
        if (!isEduSeen()) {
            mHotseatEduController = new HotseatEduController(mLauncher, this::createPredictor);
            mHotseatEduController = new HotseatEduController(mLauncher, mRestoreHelper,
                    this::createPredictor);
        }
    }

@@ -320,9 +324,11 @@ public class HotseatPredictionController implements DragController.DragListener,
        updateDependencies();
        bindItems(items, false, null);
    }

    private void setPredictedApps(List<AppTarget> appTargets) {
        mComponentKeyMappers.clear();
        if (appTargets.isEmpty() && mRestoreHelper.shouldRestoreToBackup()) {
            mRestoreHelper.restoreBackup();
        }
        StringBuilder predictionLog = new StringBuilder("predictedApps: [\n");
        ArrayList<ComponentKey> componentKeys = new ArrayList<>();
        for (AppTarget appTarget : appTargets) {
+100 −0
Original line number Diff line number Diff line
/*
 * 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.hybridhotseat;

import static com.android.launcher3.LauncherSettings.Favorites.HYBRID_HOTSEAT_BACKUP_TABLE;
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;

import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.GridBackupTable;
import com.android.launcher3.provider.LauncherDbUtils;

/**
 * A helper class to manage migration revert restoration for hybrid hotseat
 */
public class HotseatRestoreHelper {
    private final Launcher mLauncher;
    private boolean mBackupExists;

    HotseatRestoreHelper(Launcher context) {
        mLauncher = context;
        setupBackupTable();
    }

    /**
     * Creates a snapshot backup of Favorite table for future restoration use.
     */
    public synchronized void createBackup() {
        try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
                LauncherSettings.Settings.call(
                        mLauncher.getContentResolver(),
                        LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
                        .getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
            InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
            GridBackupTable backupTable = new GridBackupTable(mLauncher,
                    transaction.getDb(), idp.numHotseatIcons, idp.numColumns,
                    idp.numRows);
            backupTable.createCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE);
            transaction.commit();
            LauncherSettings.Settings.call(mLauncher.getContentResolver(),
                    LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE);
            mBackupExists = true;
        }
    }

    /**
     * Finds and restores a previously saved snapshow of Favorites table
     */
    public void restoreBackup() {
        try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
                LauncherSettings.Settings.call(
                        mLauncher.getContentResolver(),
                        LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
                        .getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
            if (!tableExists(transaction.getDb(), HYBRID_HOTSEAT_BACKUP_TABLE)) {
                mBackupExists = false;
                return;
            }
            InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
            GridBackupTable backupTable = new GridBackupTable(mLauncher,
                    transaction.getDb(), idp.numHotseatIcons, idp.numColumns,
                    idp.numRows);
            backupTable.restoreFromCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE, true);
            transaction.commit();
            mBackupExists = false;
            mLauncher.getModel().forceReload();
        }
    }

    /**
     * Returns if prediction controller should attempt restoring a backup
     */
    public synchronized boolean shouldRestoreToBackup() {
        return mBackupExists;
    }

    private synchronized void setupBackupTable() {
        try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
                LauncherSettings.Settings.call(
                        mLauncher.getContentResolver(),
                        LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
                        .getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
            mBackupExists = tableExists(transaction.getDb(), HYBRID_HOTSEAT_BACKUP_TABLE);
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@
    <string name="hotseat_tip_no_empty_slots">Drag apps off the bottom row to get app suggestions</string>
    <!-- tip shown if user declines migration and has some open spots for prediction -->
    <string name="hotseat_tip_gaps_filled">App suggestions added to empty space</string>
    <!-- tip shown when user migrates and predictions are enabled in hotseat -->
    <string name="hotsaet_tip_prediction_enabled">App suggestions Enabled</string>

    <!-- content description for hotseat items -->
    <string name="hotseat_prediction_content_description">Predicted app: <xliff:g id="title" example="Chrome">%1$s</xliff:g></string>
Loading