Search in sources :

Example 61 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ArrowOS.

the class WidgetsTableUtils method groupWidgetItemsIntoTableWithoutReordering.

/**
 * Groups {@code widgetItems} into a 2D array which matches their appearance in a UI table while
 * maintaining their order.
 *
 * <p>Grouping:
 * 1. Widgets and shortcuts never group together in the same row.
 * 2. The ordered widgets are grouped together in the same row until their total horizontal
 *    spans exceed the {@code maxSpansPerRow} - 1.
 * 3. The order shortcuts are grouped together in the same row until their total horizontal
 *    spans exceed the {@code maxSpansPerRow} - 1.
 * 4. If there is only one widget in a row, its width may exceed the {@code maxSpansPerRow}.
 *
 * <p>Let's say the {@code maxSpansPerRow} is set to 6. Widgets can be grouped in the same row
 * if their total horizontal spans added don't exceed 5.
 * Example 1: Row 1: 2x2, 2x3, 1x1. Total horizontal spans is 5. This is okay.
 * Example 2: Row 1: 2x2, 4x3, 1x1. the total horizontal spans is 7. This is wrong. 4x3 and 1x1
 * should be moved to a new row.
 * Example 3: Row 1: 6x4. This is okay because this is the only item in the row.
 */
public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTableWithoutReordering(List<WidgetItem> widgetItems, final int maxSpansPerRow) {
    List<ArrayList<WidgetItem>> widgetItemsTable = new ArrayList<>();
    ArrayList<WidgetItem> widgetItemsAtRow = null;
    for (WidgetItem widgetItem : widgetItems) {
        if (widgetItemsAtRow == null) {
            widgetItemsAtRow = new ArrayList<>();
            widgetItemsTable.add(widgetItemsAtRow);
        }
        int numOfWidgetItems = widgetItemsAtRow.size();
        int totalHorizontalSpan = widgetItemsAtRow.stream().map(item -> item.spanX).reduce(/* default= */
        0, Integer::sum);
        int totalHorizontalSpanAfterAddingWidget = widgetItem.spanX + totalHorizontalSpan;
        if (numOfWidgetItems == 0) {
            widgetItemsAtRow.add(widgetItem);
        } else if (// widget's description.
        totalHorizontalSpanAfterAddingWidget <= maxSpansPerRow - 1 && widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))) {
            // Group items in the same row if
            // 1. they are with the same type, i.e. a row can only have widgets or shortcuts but
            // never a mix of both.
            // 2. the total number of horizontal spans are smaller than or equal to
            // MAX_SPAN_PER_ROW. If an item has a horizontal span > MAX_SPAN_PER_ROW, we just
            // place it in its own row regardless of the horizontal span limit.
            widgetItemsAtRow.add(widgetItem);
        } else {
            widgetItemsAtRow = new ArrayList<>();
            widgetItemsTable.add(widgetItemsAtRow);
            widgetItemsAtRow.add(widgetItem);
        }
    }
    return widgetItemsTable;
}
Also used : List(java.util.List) WidgetItem(com.android.launcher3.model.WidgetItem) Comparator(java.util.Comparator) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) WidgetItem(com.android.launcher3.model.WidgetItem)

Example 62 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ArrowOS.

the class LoaderTask method run.

public void run() {
    synchronized (this) {
        // Skip fast if we are already stopped.
        if (mStopped) {
            return;
        }
    }
    Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
    TimingLogger logger = new TimingLogger(TAG, "run");
    LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
    try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
        List<ShortcutInfo> allShortcuts = new ArrayList<>();
        Trace.beginSection("LoadWorkspace");
        try {
            loadWorkspace(allShortcuts, memoryLogger);
        } finally {
            Trace.endSection();
        }
        logASplit(logger, "loadWorkspace");
        // (e.g. both grid preview and minimal device mode uses a different db)
        if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {
            verifyNotStopped();
            sanitizeData();
            logASplit(logger, "sanitizeData");
        }
        verifyNotStopped();
        mResults.bindWorkspace(true);
        logASplit(logger, "bindWorkspace");
        mModelDelegate.workspaceLoadComplete();
        // Notify the installer packages of packages with active installs on the first screen.
        sendFirstScreenActiveInstallsBroadcast();
        logASplit(logger, "sendFirstScreenActiveInstallsBroadcast");
        // Take a break
        waitForIdle();
        logASplit(logger, "step 1 complete");
        verifyNotStopped();
        // second step
        Trace.beginSection("LoadAllApps");
        List<LauncherActivityInfo> allActivityList;
        try {
            allActivityList = loadAllApps();
        } finally {
            Trace.endSection();
        }
        logASplit(logger, "loadAllApps");
        verifyNotStopped();
        mResults.bindAllApps();
        logASplit(logger, "bindAllApps");
        verifyNotStopped();
        IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
        setIgnorePackages(updateHandler);
        updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.newInstance(mApp.getContext()), mApp.getModel()::onPackageIconsUpdated);
        logASplit(logger, "update icon cache");
        if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
            verifyNotStopped();
            logASplit(logger, "save shortcuts in icon cache");
            updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), mApp.getModel()::onPackageIconsUpdated);
        }
        // Take a break
        waitForIdle();
        logASplit(logger, "step 2 complete");
        verifyNotStopped();
        // third step
        List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
        logASplit(logger, "loadDeepShortcuts");
        verifyNotStopped();
        mResults.bindDeepShortcuts();
        logASplit(logger, "bindDeepShortcuts");
        if (FeatureFlags.ENABLE_DEEP_SHORTCUT_ICON_CACHE.get()) {
            verifyNotStopped();
            logASplit(logger, "save deep shortcuts in icon cache");
            updateHandler.updateIcons(allDeepShortcuts, new ShortcutCachingLogic(), (pkgs, user) -> {
            });
        }
        // Take a break
        waitForIdle();
        logASplit(logger, "step 3 complete");
        verifyNotStopped();
        // fourth step
        List<ComponentWithLabelAndIcon> allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null);
        logASplit(logger, "load widgets");
        verifyNotStopped();
        mResults.bindWidgets();
        logASplit(logger, "bindWidgets");
        verifyNotStopped();
        updateHandler.updateIcons(allWidgetsList, new ComponentWithIconCachingLogic(mApp.getContext(), true), mApp.getModel()::onWidgetLabelsUpdated);
        logASplit(logger, "save widgets in icon cache");
        // fifth step
        if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
            loadFolderNames();
        }
        verifyNotStopped();
        updateHandler.finish();
        logASplit(logger, "finish icon update");
        mModelDelegate.modelLoadComplete();
        transaction.commit();
        memoryLogger.clearLogs();
    } catch (CancellationException e) {
        // Loader stopped, ignore
        logASplit(logger, "Cancelled");
    } catch (Exception e) {
        memoryLogger.printLogs();
        throw e;
    } finally {
        logger.dumpToLog();
    }
    TraceHelper.INSTANCE.endSection(traceToken);
}
Also used : LauncherModel(com.android.launcher3.LauncherModel) ShortcutInfo(android.content.pm.ShortcutInfo) ArrayList(java.util.ArrayList) ShortcutCachingLogic(com.android.launcher3.icons.ShortcutCachingLogic) CancellationException(java.util.concurrent.CancellationException) ComponentWithIconCachingLogic(com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic) TimingLogger(android.util.TimingLogger) CancellationException(java.util.concurrent.CancellationException) LauncherActivityInfo(android.content.pm.LauncherActivityInfo) ComponentWithLabelAndIcon(com.android.launcher3.icons.ComponentWithLabelAndIcon) IconCacheUpdateHandler(com.android.launcher3.icons.cache.IconCacheUpdateHandler)

Example 63 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ArrowOS.

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 : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) CONTAINER_WIDGETS_PREDICTION(com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION) Arrays(java.util.Arrays) MODEL_EXECUTOR(com.android.launcher3.util.Executors.MODEL_EXECUTOR) AppTargetId(android.app.prediction.AppTargetId) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Mock(org.mockito.Mock) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) RunWith(org.junit.runner.RunWith) AppWidgetProviderInfo(android.appwidget.AppWidgetProviderInfo) AndroidJUnit4(androidx.test.ext.junit.runners.AndroidJUnit4) IconCache(com.android.launcher3.icons.IconCache) AppTarget(android.app.prediction.AppTarget) MockitoAnnotations(org.mockito.MockitoAnnotations) Process.myUserHandle(android.os.Process.myUserHandle) Mockito.doAnswer(org.mockito.Mockito.doAnswer) UserHandle(android.os.UserHandle) After(org.junit.After) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) WidgetUtils.createAppWidgetProviderInfo(com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo) Mockito.doReturn(org.mockito.Mockito.doReturn) Log(android.util.Log) Before(org.junit.Before) SmallTest(androidx.test.filters.SmallTest) LauncherModelHelper(com.android.launcher3.util.LauncherModelHelper) ComponentName(android.content.ComponentName) LauncherAppState(com.android.launcher3.LauncherAppState) TextUtils(android.text.TextUtils) FeatureFlags(com.android.launcher3.config.FeatureFlags) Test(org.junit.Test) Truth.assertThat(com.google.common.truth.Truth.assertThat) Collectors(java.util.stream.Collectors) AppWidgetManager(android.appwidget.AppWidgetManager) List(java.util.List) LauncherAppWidgetProviderInfo(com.android.launcher3.widget.LauncherAppWidgetProviderInfo) FixedContainerItems(com.android.launcher3.model.BgDataModel.FixedContainerItems) ComponentWithLabel(com.android.launcher3.icons.ComponentWithLabel) PredictorState(com.android.launcher3.model.QuickstepModelDelegate.PredictorState) AppTarget(android.app.prediction.AppTarget) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) AppTargetId(android.app.prediction.AppTargetId) SmallTest(androidx.test.filters.SmallTest) Test(org.junit.Test)

Example 64 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ArrowOS.

the class WidgetsPredicationUpdateTaskTest method widgetsRecommendationRan_localFilterDisabled_shouldReturnWidgetsInPredicationOrder.

@Test
public void widgetsRecommendationRan_localFilterDisabled_shouldReturnWidgetsInPredicationOrder() throws Exception {
    if (FeatureFlags.ENABLE_LOCAL_RECOMMENDED_WIDGETS_FILTER.get()) {
        return;
    }
    // WHEN newPredicationTask is executed with 5 predicated widgets.
    AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1", mUserHandle);
    AppTarget widget2 = new AppTarget(new AppTargetId("app1"), "app1", "provider2", mUserHandle);
    // Not installed app
    AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1", mUserHandle);
    // Not installed widget
    AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider3", mUserHandle);
    AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1", mUserHandle);
    mModelHelper.executeTaskForTest(newWidgetsPredicationTask(List.of(widget5, widget3, widget2, widget4, widget1))).forEach(Runnable::run);
    // THEN only 3 widgets are returned because the launcher only filters out non-exist widgets.
    List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items.stream().map(itemInfo -> (PendingAddWidgetInfo) itemInfo).collect(Collectors.toList());
    assertThat(recommendedWidgets).hasSize(3);
    assertWidgetInfo(recommendedWidgets.get(0).info, mApp5Provider1);
    assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider2);
    assertWidgetInfo(recommendedWidgets.get(2).info, mApp1Provider1);
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) CONTAINER_WIDGETS_PREDICTION(com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION) Arrays(java.util.Arrays) MODEL_EXECUTOR(com.android.launcher3.util.Executors.MODEL_EXECUTOR) AppTargetId(android.app.prediction.AppTargetId) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) Mock(org.mockito.Mock) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) RunWith(org.junit.runner.RunWith) AppWidgetProviderInfo(android.appwidget.AppWidgetProviderInfo) AndroidJUnit4(androidx.test.ext.junit.runners.AndroidJUnit4) IconCache(com.android.launcher3.icons.IconCache) AppTarget(android.app.prediction.AppTarget) MockitoAnnotations(org.mockito.MockitoAnnotations) Process.myUserHandle(android.os.Process.myUserHandle) Mockito.doAnswer(org.mockito.Mockito.doAnswer) UserHandle(android.os.UserHandle) After(org.junit.After) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) WidgetUtils.createAppWidgetProviderInfo(com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo) Mockito.doReturn(org.mockito.Mockito.doReturn) Log(android.util.Log) Before(org.junit.Before) SmallTest(androidx.test.filters.SmallTest) LauncherModelHelper(com.android.launcher3.util.LauncherModelHelper) ComponentName(android.content.ComponentName) LauncherAppState(com.android.launcher3.LauncherAppState) TextUtils(android.text.TextUtils) FeatureFlags(com.android.launcher3.config.FeatureFlags) Test(org.junit.Test) Truth.assertThat(com.google.common.truth.Truth.assertThat) Collectors(java.util.stream.Collectors) AppWidgetManager(android.appwidget.AppWidgetManager) List(java.util.List) LauncherAppWidgetProviderInfo(com.android.launcher3.widget.LauncherAppWidgetProviderInfo) FixedContainerItems(com.android.launcher3.model.BgDataModel.FixedContainerItems) ComponentWithLabel(com.android.launcher3.icons.ComponentWithLabel) PredictorState(com.android.launcher3.model.QuickstepModelDelegate.PredictorState) AppTarget(android.app.prediction.AppTarget) PendingAddWidgetInfo(com.android.launcher3.widget.PendingAddWidgetInfo) AppTargetId(android.app.prediction.AppTargetId) SmallTest(androidx.test.filters.SmallTest) Test(org.junit.Test)

Example 65 with WIDGETS

use of com.android.launcher3.popup.SystemShortcut.WIDGETS in project android_packages_apps_Launcher3 by ArrowOS.

the class AppWidgetsRestoredReceiver method restoreAppWidgetIds.

/**
 * Updates the app widgets whose id has changed during the restore process.
 */
@WorkerThread
public static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds) {
    AppWidgetHost appWidgetHost = new LauncherAppWidgetHost(context);
    if (WidgetsModel.GO_DISABLE_WIDGETS) {
        Log.e(TAG, "Skipping widget ID remap as widgets not supported");
        appWidgetHost.deleteHost();
        return;
    }
    if (!RestoreDbTask.isPending(context)) {
        // Someone has already gone through our DB once, probably LoaderTask. Skip any further
        // modifications of the DB.
        Log.e(TAG, "Skipping widget ID remap as DB already in use");
        for (int widgetId : newWidgetIds) {
            Log.d(TAG, "Deleting widgetId: " + widgetId);
            appWidgetHost.deleteAppWidgetId(widgetId);
        }
        return;
    }
    final ContentResolver cr = context.getContentResolver();
    final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
    for (int i = 0; i < oldWidgetIds.length; i++) {
        Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
        final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
        final int state;
        if (LoaderTask.isValidProvider(provider)) {
            // This will ensure that we show 'Click to setup' UI if required.
            state = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
        } else {
            state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
        }
        // b/135926478: Work profile widget restore is broken in platform. This forces us to
        // recreate the widget during loading with the correct host provider.
        long mainProfileId = UserCache.INSTANCE.get(context).getSerialNumberForUser(myUserHandle());
        String oldWidgetId = Integer.toString(oldWidgetIds[i]);
        final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
        final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) };
        int result = new ContentWriter(context, new ContentWriter.CommitParams(where, args)).put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]).put(LauncherSettings.Favorites.RESTORED, state).commit();
        if (result == 0) {
            Cursor cursor = cr.query(Favorites.CONTENT_URI, new String[] { Favorites.APPWIDGET_ID }, "appWidgetId=?", new String[] { oldWidgetId }, null);
            try {
                if (!cursor.moveToFirst()) {
                    // The widget no long exists.
                    appWidgetHost.deleteAppWidgetId(newWidgetIds[i]);
                }
            } finally {
                cursor.close();
            }
        }
        // attempt to update widget id in backup table as well
        new ContentWriter(context, ContentWriter.CommitParams.backupCommitParams("appWidgetId=? and profileId=?", args)).put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]).put(LauncherSettings.Favorites.RESTORED, state).commit();
    }
    LauncherAppState app = LauncherAppState.getInstanceNoCreate();
    if (app != null) {
        app.getModel().forceReload();
    }
}
Also used : AppWidgetHost(android.appwidget.AppWidgetHost) LauncherAppWidgetHost(com.android.launcher3.widget.LauncherAppWidgetHost) AppWidgetManager(android.appwidget.AppWidgetManager) Cursor(android.database.Cursor) ContentResolver(android.content.ContentResolver) ContentWriter(com.android.launcher3.util.ContentWriter) LauncherAppWidgetHost(com.android.launcher3.widget.LauncherAppWidgetHost) AppWidgetProviderInfo(android.appwidget.AppWidgetProviderInfo) WorkerThread(androidx.annotation.WorkerThread)

Aggregations

ArrayList (java.util.ArrayList)64 Test (org.junit.Test)64 WidgetItem (com.android.launcher3.model.WidgetItem)54 WidgetsListContentEntry (com.android.launcher3.widget.model.WidgetsListContentEntry)54 PackageUserKey (com.android.launcher3.util.PackageUserKey)50 List (java.util.List)50 AppWidgetProviderInfo (android.appwidget.AppWidgetProviderInfo)46 SmallTest (androidx.test.filters.SmallTest)44 ComponentName (android.content.ComponentName)42 WidgetsListBaseEntry (com.android.launcher3.widget.model.WidgetsListBaseEntry)41 Point (android.graphics.Point)40 View (android.view.View)37 LauncherAppWidgetHostView (com.android.launcher3.widget.LauncherAppWidgetHostView)32 Collectors (java.util.stream.Collectors)31 Context (android.content.Context)29 IconCache (com.android.launcher3.icons.IconCache)29 LauncherAppWidgetProviderInfo (com.android.launcher3.widget.LauncherAppWidgetProviderInfo)29 WidgetsListHeaderEntry (com.android.launcher3.widget.model.WidgetsListHeaderEntry)29 WorkspaceItemInfo (com.android.launcher3.model.data.WorkspaceItemInfo)27 PendingAddWidgetInfo (com.android.launcher3.widget.PendingAddWidgetInfo)27