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

Commit d6b8934d authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6559824 from d5fed545 to mainline-release

Change-Id: I374471441793df737cdd7062709fe972e96d50b2
parents f48a5043 d5fed545
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ message ContainerInfo {
    WidgetsContainer widgets_container = 5;
    PredictionContainer prediction_container = 6;
    SearchResultContainer search_result_container = 7;
    ShortcutsContainer shortcuts_container = 8;
  }
}

@@ -69,6 +70,11 @@ message PredictionContainer {
message SearchResultContainer {
}

// Container for package specific shortcuts to deep links and notifications.
// Typically shown as popup window by longpressing on an icon.
message ShortcutsContainer {
}

enum Origin {
  UNKNOWN = 0;
  DEFAULT_LAYOUT = 1;       // icon automatically placed in workspace, folder, hotseat
+9 −72
Original line number Diff line number Diff line
@@ -15,17 +15,9 @@
 */
package com.android.launcher3.hybridhotseat;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Build;
import android.view.View;

import androidx.core.app.NotificationCompat;

import com.android.launcher3.CellLayout;
import com.android.launcher3.Hotseat;
import com.android.launcher3.InvariantDeviceProfile;
@@ -37,11 +29,8 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ArrowTipView;
import com.android.launcher3.views.Snackbar;

@@ -54,18 +43,16 @@ import java.util.stream.IntStream;
 * Controller class for managing user onboaridng flow for hybrid hotseat
 */
public class HotseatEduController {
    public static final String KEY_HOTSEAT_EDU_SEEN = "hotseat_edu_seen";

    private static final String NOTIFICATION_CHANNEL_ID = "launcher_onboarding";
    private static final int ONBOARDING_NOTIFICATION_ID = 7641;

    public static final String KEY_HOTSEAT_EDU_SEEN = "hotseat_edu_seen";
    public static final String HOTSEAT_EDU_ACTION =
            "com.android.launcher3.action.SHOW_HYBRID_HOTSEAT_EDU";
    private static final String SETTINGS_ACTION =
            "android.settings.ACTION_CONTENT_SUGGESTIONS_SETTINGS";

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

@@ -73,24 +60,25 @@ 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;
        mNotificationManager = mLauncher.getSystemService(NotificationManager.class);
        createNotificationChannel();
        mNotification = createNotification();
    }

    /**
     * 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)));
    }

    /**
@@ -101,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
@@ -216,11 +203,6 @@ public class HotseatEduController {
        return pageId;
    }


    void removeNotification() {
        mNotificationManager.cancel(ONBOARDING_NOTIFICATION_ID);
    }

    void moveHotseatItems() {
        mHotseat.removeAllViewsInLayout();
        if (!mNewItems.isEmpty()) {
@@ -258,45 +240,9 @@ public class HotseatEduController {

    void setPredictedApps(List<WorkspaceItemInfo> predictedApps) {
        mPredictedApps = predictedApps;
        if (!mPredictedApps.isEmpty()
                && mLauncher.getOrientation() == Configuration.ORIENTATION_PORTRAIT) {
            mNotificationManager.notify(ONBOARDING_NOTIFICATION_ID, mNotification);
        }
        else {
            removeNotification();
        }
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
        CharSequence name = mLauncher.getString(R.string.hotseat_edu_prompt_title);
        int importance = NotificationManager.IMPORTANCE_LOW;
        NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name,
                importance);
        mNotificationManager.createNotificationChannel(channel);
    }

    private Notification createNotification() {
        Intent intent = new Intent(mLauncher.getApplicationContext(), mLauncher.getClass());
        intent = new NotificationHandler().addToIntent(intent);

        CharSequence name = mLauncher.getString(R.string.hotseat_edu_prompt_title);
        String description = mLauncher.getString(R.string.hotseat_edu_prompt_content);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(mLauncher,
                NOTIFICATION_CHANNEL_ID)
                .setContentTitle(name)
                .setOngoing(true)
                .setColor(Themes.getColorAccent(mLauncher))
                .setContentIntent(PendingIntent.getActivity(mLauncher, 0, intent,
                        PendingIntent.FLAG_CANCEL_CURRENT))
                .setSmallIcon(R.drawable.hotseat_edu_notification_icon)
                .setContentText(description);
        return builder.build();

    }

    void destroy() {
        removeNotification();
        if (mActiveDialog != null) {
            mActiveDialog.setHotseatEduController(null);
        }
@@ -334,14 +280,5 @@ public class HotseatEduController {
        mActiveDialog.setHotseatEduController(this);
        mActiveDialog.show(mPredictedApps);
    }

    static class NotificationHandler implements
            ActivityTracker.SchedulerCallback<QuickstepLauncher> {
        @Override
        public boolean init(QuickstepLauncher activity, boolean alreadyOnHome) {
            activity.getHotseatPredictionController().showEdu();
            return true;
        }
    }
}
+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;
+9 −5
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsStore;
@@ -93,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;
@@ -130,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);
        }
@@ -148,8 +150,7 @@ public class HotseatPredictionController implements DragController.DragListener,
     */
    public void showEdu() {
        if (mHotseatEduController == null) return;
        mLauncher.getStateManager().goToState(LauncherState.NORMAL, true,
                () -> mHotseatEduController.showEdu());
        mHotseatEduController.showEdu();
    }

    @Override
@@ -299,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);
        }
    }

@@ -322,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);
        }
    }
}
Loading