Search in sources :

Example 6 with Workspace

use of com.android.launcher3.tapl.Workspace in project android_packages_apps_Launcher3 by crdroidandroid.

the class WidgetsPredictionUpdateTask method execute.

/**
 * Uses the app predication result to infer widgets that the user may want to use.
 *
 * <p>The algorithm uses the app prediction ranking to create a widgets ranking which only
 * includes one widget per app and excludes widgets that have already been added to the
 * workspace.
 */
@Override
public void execute(LauncherAppState appState, BgDataModel dataModel, AllAppsList apps) {
    Set<ComponentKey> widgetsInWorkspace = dataModel.appWidgets.stream().map(widget -> new ComponentKey(widget.providerName, widget.user)).collect(Collectors.toSet());
    Map<PackageUserKey, List<WidgetItem>> allWidgets = dataModel.widgetsModel.getAllWidgetsWithoutShortcuts();
    FixedContainerItems fixedContainerItems = mPredictorState.items;
    fixedContainerItems.items.clear();
    if (FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER.get()) {
        for (AppTarget app : mTargets) {
            PackageUserKey packageUserKey = new PackageUserKey(app.getPackageName(), app.getUser());
            if (allWidgets.containsKey(packageUserKey)) {
                List<WidgetItem> notAddedWidgets = allWidgets.get(packageUserKey).stream().filter(item -> !widgetsInWorkspace.contains(new ComponentKey(item.componentName, item.user))).collect(Collectors.toList());
                if (notAddedWidgets.size() > 0) {
                    // Even an apps have more than one widgets, we only include one widget.
                    fixedContainerItems.items.add(new PendingAddWidgetInfo(notAddedWidgets.get(0).widgetInfo, CONTAINER_WIDGETS_PREDICTION));
                }
            }
        }
    } else {
        Map<ComponentKey, WidgetItem> widgetItems = allWidgets.values().stream().flatMap(List::stream).collect(Collectors.toMap(widget -> (ComponentKey) widget, widget -> widget));
        for (AppTarget app : mTargets) {
            if (TextUtils.isEmpty(app.getClassName())) {
                continue;
            }
            ComponentKey targetWidget = new ComponentKey(new ComponentName(app.getPackageName(), app.getClassName()), app.getUser());
            if (widgetItems.containsKey(targetWidget)) {
                fixedContainerItems.items.add(new PendingAddWidgetInfo(widgetItems.get(targetWidget).widgetInfo, CONTAINER_WIDGETS_PREDICTION));
            }
        }
    }
    bindExtraContainerItems(fixedContainerItems);
// Don't store widgets prediction to disk because it is not used frequently.
}
Also used : CONTAINER_WIDGETS_PREDICTION(com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION) ComponentName(android.content.ComponentName) LauncherAppState(com.android.launcher3.LauncherAppState) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) PackageUserKey(com.android.launcher3.util.PackageUserKey) Set(java.util.Set) TextUtils(android.text.TextUtils) FeatureFlags(com.android.launcher3.config.FeatureFlags) Collectors(java.util.stream.Collectors) AppTarget(android.app.prediction.AppTarget) List(java.util.List) ComponentKey(com.android.launcher3.util.ComponentKey) Map(java.util.Map) FixedContainerItems(com.android.launcher3.model.BgDataModel.FixedContainerItems) PredictorState(com.android.launcher3.model.QuickstepModelDelegate.PredictorState) ComponentKey(com.android.launcher3.util.ComponentKey) PackageUserKey(com.android.launcher3.util.PackageUserKey) FixedContainerItems(com.android.launcher3.model.BgDataModel.FixedContainerItems) AppTarget(android.app.prediction.AppTarget) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) List(java.util.List) ComponentName(android.content.ComponentName)

Example 7 with Workspace

use of com.android.launcher3.tapl.Workspace in project android_packages_apps_Launcher3 by crdroidandroid.

the class WidgetsPredicationUpdateTaskTest method setup.

@Before
public void setup() throws Exception {
    MockitoAnnotations.initMocks(this);
    doAnswer(invocation -> {
        ComponentWithLabel componentWithLabel = invocation.getArgument(0);
        return componentWithLabel.getComponent().getShortClassName();
    }).when(mIconCache).getTitleNoCache(any());
    mContext = RuntimeEnvironment.application;
    mModelHelper = new LauncherModelHelper();
    mUserHandle = Process.myUserHandle();
    mTestProfile = new InvariantDeviceProfile();
    // 2 widgets, app4/provider1 & app5/provider1, have already been added to the workspace.
    mModelHelper.initializeData("/widgets_predication_update_task_data.txt");
    ShadowPackageManager packageManager = shadowOf(mContext.getPackageManager());
    mApp1Provider1.provider = ComponentName.createRelative("app1", "provider1");
    ReflectionHelpers.setField(mApp1Provider1, "providerInfo", packageManager.addReceiverIfNotPresent(mApp1Provider1.provider));
    mApp1Provider2.provider = ComponentName.createRelative("app1", "provider2");
    ReflectionHelpers.setField(mApp1Provider2, "providerInfo", packageManager.addReceiverIfNotPresent(mApp1Provider2.provider));
    mApp2Provider1.provider = ComponentName.createRelative("app2", "provider1");
    ReflectionHelpers.setField(mApp2Provider1, "providerInfo", packageManager.addReceiverIfNotPresent(mApp2Provider1.provider));
    mApp4Provider1.provider = ComponentName.createRelative("app4", "provider1");
    ReflectionHelpers.setField(mApp4Provider1, "providerInfo", packageManager.addReceiverIfNotPresent(mApp4Provider1.provider));
    mApp4Provider2.provider = ComponentName.createRelative("app4", ".provider2");
    ReflectionHelpers.setField(mApp4Provider2, "providerInfo", packageManager.addReceiverIfNotPresent(mApp4Provider2.provider));
    mApp5Provider1.provider = ComponentName.createRelative("app5", "provider1");
    ReflectionHelpers.setField(mApp5Provider1, "providerInfo", packageManager.addReceiverIfNotPresent(mApp5Provider1.provider));
    ShadowAppWidgetManager shadowAppWidgetManager = shadowOf(mContext.getSystemService(AppWidgetManager.class));
    shadowAppWidgetManager.addInstalledProvider(mApp1Provider1);
    shadowAppWidgetManager.addInstalledProvider(mApp1Provider2);
    shadowAppWidgetManager.addInstalledProvider(mApp2Provider1);
    shadowAppWidgetManager.addInstalledProvider(mApp4Provider1);
    shadowAppWidgetManager.addInstalledProvider(mApp4Provider2);
    shadowAppWidgetManager.addInstalledProvider(mApp5Provider1);
    mModelHelper.getModel().addCallbacks(mCallback);
    MODEL_EXECUTOR.post(() -> mModelHelper.getBgDataModel().widgetsModel.update(LauncherAppState.getInstance(mContext), /* packageUser= */
    null));
    waitUntilIdle();
}
Also used : ShadowPackageManager(org.robolectric.shadows.ShadowPackageManager) LauncherModelHelper(com.android.launcher3.util.LauncherModelHelper) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) ShadowAppWidgetManager(org.robolectric.shadows.ShadowAppWidgetManager) AppWidgetManager(android.appwidget.AppWidgetManager) ComponentWithLabel(com.android.launcher3.icons.ComponentWithLabel) ShadowAppWidgetManager(org.robolectric.shadows.ShadowAppWidgetManager) Before(org.junit.Before)

Example 8 with Workspace

use of com.android.launcher3.tapl.Workspace in project android_packages_apps_Launcher3 by crdroidandroid.

the class WidgetsPredicationUpdateTaskTest method widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder.

@Test
public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder() throws Exception {
    // WHEN newPredicationTask is executed with app predication of 5 apps.
    AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "className", mUserHandle);
    AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "className", mUserHandle);
    AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className", mUserHandle);
    AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "className", mUserHandle);
    AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "className", mUserHandle);
    mModelHelper.executeTaskForTest(newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1))).forEach(Runnable::run);
    // THEN only 3 widgets are returned because
    // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
    // excluded from the result.
    // 2. app3 doesn't have a widget.
    // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
    List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items.stream().map(itemInfo -> (PendingAddWidgetInfo) itemInfo).collect(Collectors.toList());
    assertThat(recommendedWidgets).hasSize(3);
    assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
    assertWidgetInfo(recommendedWidgets.get(1).info, mApp4Provider2);
    assertWidgetInfo(recommendedWidgets.get(2).info, mApp1Provider1);
}
Also used : CONTAINER_WIDGETS_PREDICTION(com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION) ViewOnDrawExecutor(com.android.launcher3.util.ViewOnDrawExecutor) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) AppWidgetProviderInfo(android.appwidget.AppWidgetProviderInfo) IconCache(com.android.launcher3.icons.IconCache) AppTarget(android.app.prediction.AppTarget) Process(android.os.Process) MockitoAnnotations(org.mockito.MockitoAnnotations) ReflectionHelpers(org.robolectric.util.ReflectionHelpers) Mockito.doAnswer(org.mockito.Mockito.doAnswer) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) ShadowDeviceFlag(com.android.launcher3.shadows.ShadowDeviceFlag) LauncherModelHelper(com.android.launcher3.util.LauncherModelHelper) Shadow(org.robolectric.shadow.api.Shadow) RuntimeEnvironment(org.robolectric.RuntimeEnvironment) Collectors(java.util.stream.Collectors) RobolectricTestRunner(org.robolectric.RobolectricTestRunner) List(java.util.List) LauncherAppWidgetProviderInfo(com.android.launcher3.widget.LauncherAppWidgetProviderInfo) FixedContainerItems(com.android.launcher3.model.BgDataModel.FixedContainerItems) ComponentWithLabel(com.android.launcher3.icons.ComponentWithLabel) ItemInfoMatcher(com.android.launcher3.util.ItemInfoMatcher) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) Context(android.content.Context) MODEL_EXECUTOR(com.android.launcher3.util.Executors.MODEL_EXECUTOR) AppTargetId(android.app.prediction.AppTargetId) AppInfo(com.android.launcher3.model.data.AppInfo) Mock(org.mockito.Mock) ItemInfo(com.android.launcher3.model.data.ItemInfo) RunWith(org.junit.runner.RunWith) HashMap(java.util.HashMap) Shadows.shadowOf(org.robolectric.Shadows.shadowOf) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ShadowAppWidgetManager(org.robolectric.shadows.ShadowAppWidgetManager) WorkspaceItemInfo(com.android.launcher3.model.data.WorkspaceItemInfo) UserHandle(android.os.UserHandle) Before(org.junit.Before) IntArray(com.android.launcher3.util.IntArray) ComponentName(android.content.ComponentName) LauncherAppState(com.android.launcher3.LauncherAppState) LauncherAppWidgetInfo(com.android.launcher3.model.data.LauncherAppWidgetInfo) FeatureFlags(com.android.launcher3.config.FeatureFlags) Test(org.junit.Test) Truth.assertThat(com.google.common.truth.Truth.assertThat) AppWidgetManager(android.appwidget.AppWidgetManager) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) ShadowPackageManager(org.robolectric.shadows.ShadowPackageManager) WidgetsListBaseEntry(com.android.launcher3.widget.model.WidgetsListBaseEntry) ComponentKey(com.android.launcher3.util.ComponentKey) PredictorState(com.android.launcher3.model.QuickstepModelDelegate.PredictorState) AppTarget(android.app.prediction.AppTarget) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) AppTargetId(android.app.prediction.AppTargetId) Test(org.junit.Test)

Example 9 with Workspace

use of com.android.launcher3.tapl.Workspace in project android_packages_apps_Launcher3 by crdroidandroid.

the class GridSizeMigrationTask method migrateGridIfNeeded.

/**
 * Run the migration algorithm if needed. For preview, we provide the intended idp because it
 * has not been changed. If idp is null, we read it from the context, for actual grid migration.
 *
 * @return false if the migration failed.
 */
public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
    boolean migrateForPreview = idp != null;
    if (!migrateForPreview) {
        idp = LauncherAppState.getIDP(context);
    }
    if (!needsToMigrate(context, idp)) {
        return true;
    }
    SharedPreferences prefs = Utilities.getPrefs(context);
    String gridSizeString = getPointString(idp.numColumns, idp.numRows);
    long migrationStartTime = SystemClock.elapsedRealtime();
    try (SQLiteTransaction transaction = (SQLiteTransaction) Settings.call(context.getContentResolver(), Settings.METHOD_NEW_TRANSACTION).getBinder(Settings.EXTRA_VALUE)) {
        int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numDatabaseHotseatIcons);
        Point sourceSize = parsePoint(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString));
        boolean dbChanged = false;
        if (migrateForPreview) {
            copyTable(transaction.getDb(), Favorites.TABLE_NAME, transaction.getDb(), Favorites.PREVIEW_TABLE_NAME, context);
        }
        GridBackupTable backupTable = new GridBackupTable(context, transaction.getDb(), srcHotseatCount, sourceSize.x, sourceSize.y);
        if (migrateForPreview ? backupTable.restoreToPreviewIfBackupExists() : backupTable.backupOrRestoreAsNeeded()) {
            dbChanged = true;
            srcHotseatCount = backupTable.getRestoreHotseatAndGridSize(sourceSize);
        }
        HashSet<String> validPackages = getValidPackages(context);
        // Hotseat.
        if (srcHotseatCount != idp.numDatabaseHotseatIcons && new GridSizeMigrationTask(context, transaction.getDb(), validPackages, migrateForPreview, srcHotseatCount, idp.numDatabaseHotseatIcons).migrateHotseat()) {
            dbChanged = true;
        }
        // Grid size
        Point targetSize = new Point(idp.numColumns, idp.numRows);
        if (new MultiStepMigrationTask(validPackages, context, transaction.getDb(), migrateForPreview).migrate(sourceSize, targetSize)) {
            dbChanged = true;
        }
        if (dbChanged) {
            // Make sure we haven't removed everything.
            final Cursor c = context.getContentResolver().query(migrateForPreview ? Favorites.PREVIEW_CONTENT_URI : Favorites.CONTENT_URI, null, null, null, null);
            boolean hasData = c.moveToNext();
            c.close();
            if (!hasData) {
                throw new Exception("Removed every thing during grid resize");
            }
        }
        transaction.commit();
        if (!migrateForPreview) {
            Settings.call(context.getContentResolver(), Settings.METHOD_REFRESH_BACKUP_TABLE);
        }
        return true;
    } catch (Exception e) {
        Log.e(TAG, "Error during preview grid migration", e);
        return false;
    } finally {
        Log.v(TAG, "Preview workspace migration completed in " + (SystemClock.elapsedRealtime() - migrationStartTime));
        if (!migrateForPreview) {
            // Save current configuration, so that the migration does not run again.
            prefs.edit().putString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString).putInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numDatabaseHotseatIcons).apply();
        }
    }
}
Also used : SharedPreferences(android.content.SharedPreferences) SQLiteTransaction(com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction) Utilities.getPointString(com.android.launcher3.Utilities.getPointString) Utilities.parsePoint(com.android.launcher3.Utilities.parsePoint) Point(android.graphics.Point) Cursor(android.database.Cursor) Utilities.parsePoint(com.android.launcher3.Utilities.parsePoint) Point(android.graphics.Point)

Example 10 with Workspace

use of com.android.launcher3.tapl.Workspace in project android_packages_apps_Launcher3 by crdroidandroid.

the class GridSizeMigrationTask method migrateWorkspace.

/**
 * @return true if any DB change was made
 */
protected boolean migrateWorkspace() throws Exception {
    IntArray allScreens = getWorkspaceScreenIds(mDb, mTableName);
    if (allScreens.isEmpty()) {
        throw new Exception("Unable to get workspace screens");
    }
    for (int i = 0; i < allScreens.size(); i++) {
        int screenId = allScreens.get(i);
        if (DEBUG) {
            Log.d(TAG, "Migrating " + screenId);
        }
        migrateScreen(screenId);
    }
    if (!mCarryOver.isEmpty()) {
        IntSparseArrayMap<DbEntry> itemMap = new IntSparseArrayMap<>();
        for (DbEntry e : mCarryOver) {
            itemMap.put(e.id, e);
        }
        do {
            // Some items are still remaining. Try adding a few new screens.
            // At every iteration, make sure that at least one item is removed from
            // {@link #mCarryOver}, to prevent an infinite loop. If no item could be removed,
            // break the loop and abort migration by throwing an exception.
            OptimalPlacementSolution placement = new OptimalPlacementSolution(new GridOccupancy(mTrgX, mTrgY), deepCopy(mCarryOver), 0, true);
            placement.find();
            if (placement.finalPlacedItems.size() > 0) {
                int newScreenId = LauncherSettings.Settings.call(mContext.getContentResolver(), LauncherSettings.Settings.METHOD_NEW_SCREEN_ID).getInt(EXTRA_VALUE);
                for (DbEntry item : placement.finalPlacedItems) {
                    if (!mCarryOver.remove(itemMap.get(item.id))) {
                        throw new Exception("Unable to find matching items");
                    }
                    item.screenId = newScreenId;
                    update(item);
                }
            } else {
                throw new Exception("None of the items can be placed on an empty screen");
            }
        } while (!mCarryOver.isEmpty());
    }
    return applyOperations();
}
Also used : IntArray(com.android.launcher3.util.IntArray) IntSparseArrayMap(com.android.launcher3.util.IntSparseArrayMap) GridOccupancy(com.android.launcher3.util.GridOccupancy) Utilities.parsePoint(com.android.launcher3.Utilities.parsePoint) Point(android.graphics.Point)

Aggregations

View (android.view.View)143 WorkspaceItemInfo (com.android.launcher3.model.data.WorkspaceItemInfo)124 Point (android.graphics.Point)115 LauncherAppWidgetHostView (com.android.launcher3.widget.LauncherAppWidgetHostView)97 Rect (android.graphics.Rect)93 ArrayList (java.util.ArrayList)91 ItemInfo (com.android.launcher3.model.data.ItemInfo)86 DragView (com.android.launcher3.dragndrop.DragView)77 PendingAppWidgetHostView (com.android.launcher3.widget.PendingAppWidgetHostView)73 AppWidgetHostView (android.appwidget.AppWidgetHostView)72 Workspace (com.android.launcher3.Workspace)63 SuppressLint (android.annotation.SuppressLint)58 DraggableView (com.android.launcher3.dragndrop.DraggableView)58 Test (org.junit.Test)57 FolderInfo (com.android.launcher3.model.data.FolderInfo)55 CellLayout (com.android.launcher3.CellLayout)51 LauncherAppWidgetInfo (com.android.launcher3.model.data.LauncherAppWidgetInfo)47 IntArray (com.android.launcher3.util.IntArray)45 Intent (android.content.Intent)43 ValueAnimator (android.animation.ValueAnimator)41