From 1d96ba03abdf147dd4d36e746e2596e32cfdde86 Mon Sep 17 00:00:00 2001 From: Jayaprakash Sundararaj Date: Fri, 19 Jun 2020 18:31:18 -0700 Subject: [PATCH] Refactor FolderNameInfos. Bug: 159508969 Change-Id: I984e7a4fc321392d06157c705392c1ba5672f348 --- .../folder/FolderNameProviderTest.java | 17 +-- src/com/android/launcher3/folder/Folder.java | 40 ++---- .../android/launcher3/folder/FolderIcon.java | 16 ++- .../launcher3/folder/FolderNameInfo.java | 93 -------------- .../launcher3/folder/FolderNameInfos.java | 117 ++++++++++++++++++ .../launcher3/folder/FolderNameProvider.java | 46 ++++--- .../android/launcher3/model/LoaderTask.java | 7 +- .../launcher3/model/data/FolderInfo.java | 58 +++------ 8 files changed, 185 insertions(+), 209 deletions(-) delete mode 100644 src/com/android/launcher3/folder/FolderNameInfo.java create mode 100644 src/com/android/launcher3/folder/FolderNameInfos.java diff --git a/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java b/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java index d927ffc051..b7ba10696f 100644 --- a/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java +++ b/robolectric_tests/src/com/android/launcher3/folder/FolderNameProviderTest.java @@ -16,6 +16,7 @@ package com.android.launcher3.folder; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import android.content.ComponentName; import android.content.Context; @@ -61,16 +62,16 @@ public final class FolderNameProviderTest { ArrayList list = new ArrayList<>(); list.add(mItem1); list.add(mItem2); - FolderNameInfo[] nameInfos = - new FolderNameInfo[FolderNameProvider.SUGGEST_MAX]; + FolderNameInfos nameInfos = new FolderNameInfos(); new FolderNameProvider().getSuggestedFolderName(mContext, list, nameInfos); - assertEquals("Work", nameInfos[0].getLabel()); + assertEquals("Work", nameInfos.getLabels()[0]); - nameInfos[0] = new FolderNameInfo("candidate1", 0.9); - nameInfos[1] = new FolderNameInfo("candidate2", 0.8); - nameInfos[2] = new FolderNameInfo("candidate3", 0.7); + nameInfos.setLabel(0, "candidate1", 1.0f); + nameInfos.setLabel(1, "candidate2", 1.0f); + nameInfos.setLabel(2, "candidate3", 1.0f); new FolderNameProvider().getSuggestedFolderName(mContext, list, nameInfos); - assertEquals("Work", nameInfos[3].getLabel()); - + assertEquals("Work", nameInfos.getLabels()[3]); + assertTrue(nameInfos.hasSuggestions()); + assertTrue(nameInfos.hasPrimary()); } } diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index e950f3c1a0..4af3544fde 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -28,16 +28,12 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED; import static com.android.launcher3.model.data.FolderInfo.FLAG_MANUAL_FOLDER_NAME; -import static java.util.Arrays.asList; -import static java.util.Optional.ofNullable; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.annotation.SuppressLint; import android.appwidget.AppWidgetHostView; import android.content.Context; -import android.content.Intent; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.Rect; @@ -104,6 +100,7 @@ import java.util.List; import java.util.Objects; import java.util.StringJoiner; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Represents a set of icons chosen by the user or generated by the system. @@ -327,11 +324,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo public void startEditingFolderName() { post(() -> { if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { - ofNullable(mInfo) - .map(info -> info.suggestedFolderNames) - .map(folderNames -> (FolderNameInfo[]) folderNames - .getParcelableArrayExtra(FolderInfo.EXTRA_FOLDER_SUGGESTIONS)) - .ifPresent(this::showLabelSuggestions); + showLabelSuggestions(); } mFolderName.setHint(""); mIsEditingName = true; @@ -461,32 +454,24 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo * Show suggested folder title in FolderEditText if the first suggestion is non-empty, push * rest of the suggestions to InputMethodManager. */ - private void showLabelSuggestions(FolderNameInfo[] nameInfos) { - if (nameInfos == null) { + private void showLabelSuggestions() { + if (mInfo.suggestedFolderNames == null) { return; } - // Open the Folder and Keyboard when the first or second suggestion is valid non-empty - // string. - boolean shouldOpen = nameInfos.length > 0 && nameInfos[0] != null && !isEmpty( - nameInfos[0].getLabel()) - || nameInfos.length > 1 && nameInfos[1] != null && !isEmpty( - nameInfos[1].getLabel()); - - if (shouldOpen) { + if (mInfo.suggestedFolderNames.hasSuggestions()) { // update the primary suggestion if the folder name is empty. if (isEmpty(mFolderName.getText())) { - CharSequence firstLabel = nameInfos[0] == null ? "" : nameInfos[0].getLabel(); - if (!isEmpty(firstLabel)) { + if (mInfo.suggestedFolderNames.hasPrimary()) { mFolderName.setHint(""); - mFolderName.setText(firstLabel); + mFolderName.setText(mInfo.suggestedFolderNames.getLabels()[0]); mFolderName.selectAll(); } } mFolderName.showKeyboard(); mFolderName.displayCompletions( - asList(nameInfos).subList(0, nameInfos.length).stream() + Stream.of(mInfo.suggestedFolderNames.getLabels()) .filter(Objects::nonNull) - .map(s -> s.getLabel().toString()) + .map(Object::toString) .filter(s -> !s.isEmpty()) .filter(s -> !s.equalsIgnoreCase(mFolderName.getText().toString())) .collect(Collectors.toList())); @@ -1021,14 +1006,11 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo if (FeatureFlags.FOLDER_NAME_SUGGEST.get() && !isBind && total > 1 /* no need to update if there's one icon */) { Executors.MODEL_EXECUTOR.post(() -> { - FolderNameInfo[] nameInfos = - new FolderNameInfo[FolderNameProvider.SUGGEST_MAX]; + FolderNameInfos nameInfos = new FolderNameInfos(); FolderNameProvider fnp = FolderNameProvider.newInstance(getContext()); fnp.getSuggestedFolderName( getContext(), mInfo.contents, nameInfos); - mInfo.suggestedFolderNames = new Intent().putExtra( - FolderInfo.EXTRA_FOLDER_SUGGESTIONS, - nameInfos); + mInfo.suggestedFolderNames = nameInfos; }); } } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index e24033fb92..152fd370b8 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -84,7 +84,7 @@ import com.android.launcher3.widget.PendingAddShortcutInfo; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; -import java.util.stream.Stream; + /** * An icon that can appear on in the workspace representing an {@link Folder}. @@ -411,8 +411,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel if (!itemAdded) mPreviewItemManager.hidePreviewItem(index, true); final int finalIndex = index; - FolderNameInfo[] nameInfos = - new FolderNameInfo[FolderNameProvider.SUGGEST_MAX]; + FolderNameInfos nameInfos = new FolderNameInfos(); if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { Executors.MODEL_EXECUTOR.post(() -> { d.folderNameProvider.getSuggestedFolderName( @@ -428,7 +427,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel } private void showFinalView(int finalIndex, final WorkspaceItemInfo item, - FolderNameInfo[] nameInfos, InstanceId instanceId) { + FolderNameInfos nameInfos, InstanceId instanceId) { postDelayed(() -> { mPreviewItemManager.hidePreviewItem(finalIndex, false); mFolder.showItem(item); @@ -440,7 +439,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel /** * Set the suggested folder name. */ - public void setLabelSuggestion(FolderNameInfo[] nameInfos, InstanceId instanceId) { + public void setLabelSuggestion(FolderNameInfos nameInfos, InstanceId instanceId) { if (!FeatureFlags.FOLDER_NAME_SUGGEST.get()) { return; } @@ -448,22 +447,21 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel || mInfo.hasOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME)) { return; } - if (nameInfos == null || Stream.of(nameInfos) - .allMatch(nameInfo -> nameInfo == null || isEmpty(nameInfo.getLabel()))) { + if (nameInfos == null || !nameInfos.hasSuggestions()) { StatsLogManager.newInstance(getContext()).logger() .withInstanceId(instanceId) .withItemInfo(mInfo) .log(LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_SUGGESTIONS); return; } - if (nameInfos[0] == null || isEmpty(nameInfos[0].getLabel())) { + if (!nameInfos.hasPrimary()) { StatsLogManager.newInstance(getContext()).logger() .withInstanceId(instanceId) .withItemInfo(mInfo) .log(LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_PRIMARY); return; } - CharSequence newTitle = nameInfos[0].getLabel(); + CharSequence newTitle = nameInfos.getLabels()[0]; FromState fromState = mInfo.getFromLabelState(); mInfo.setTitle(newTitle); diff --git a/src/com/android/launcher3/folder/FolderNameInfo.java b/src/com/android/launcher3/folder/FolderNameInfo.java deleted file mode 100644 index 1841cd92c7..0000000000 --- a/src/com/android/launcher3/folder/FolderNameInfo.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.folder; - -import android.os.Parcel; -import android.os.Parcelable; -import android.text.TextUtils; - -import androidx.annotation.NonNull; - -/** - * Information about a single label suggestions of the Folder. - */ - -public final class FolderNameInfo implements Parcelable { - private final double mScore; - private final CharSequence mLabel; - - /** - * Create a simple completion with label. - * - * @param label The text that should be inserted into the editor and pushed to - * InputMethodManager suggestions. - * @param score The score for the label between 0.0 and 1.0. - */ - public FolderNameInfo(CharSequence label, double score) { - mScore = score; - mLabel = label; - } - - private FolderNameInfo(Parcel source) { - mScore = source.readDouble(); - mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); - } - - public CharSequence getLabel() { - return mLabel; - } - - public double getScore() { - return mScore; - } - - /** - * Used to package this object into a {@link Parcel}. - * - * @param dest The {@link Parcel} to be written. - * @param flags The flags used for parceling. - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeDouble(mScore); - TextUtils.writeToParcel(mLabel, dest, flags); - } - - /** - * Used to make this class parcelable. - */ - @NonNull - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public FolderNameInfo createFromParcel(Parcel source) { - return new FolderNameInfo(source); - } - - public FolderNameInfo[] newArray(int size) { - return new FolderNameInfo[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - @NonNull - public String toString() { - return String.format("%s:%.2f", mLabel, mScore); - } -} diff --git a/src/com/android/launcher3/folder/FolderNameInfos.java b/src/com/android/launcher3/folder/FolderNameInfos.java new file mode 100644 index 0000000000..457ae87476 --- /dev/null +++ b/src/com/android/launcher3/folder/FolderNameInfos.java @@ -0,0 +1,117 @@ +/* + * 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.folder; + +import android.text.TextUtils; + +import androidx.annotation.NonNull; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Information about a label suggestions of a Folder. + */ + +public class FolderNameInfos { + public static final int SUCCESS = 1; + public static final int HAS_PRIMARY = 1 << 1; + public static final int HAS_SUGGESTIONS = 1 << 2; + public static final int ERROR_NO_PROVIDER = 1 << 3; + public static final int ERROR_APP_LOOKUP_FAILED = 1 << 4; + public static final int ERROR_ALL_APP_LOOKUP_FAILED = 1 << 5; + public static final int ERROR_NO_LABELS_GENERATED = 1 << 6; + public static final int ERROR_LABEL_LOOKUP_FAILED = 1 << 7; + public static final int ERROR_ALL_LABEL_LOOKUP_FAILED = 1 << 8; + public static final int ERROR_NO_PACKAGES = 1 << 9; + + private int mStatus; + private final CharSequence[] mLabels; + private final Float[] mScores; + + public FolderNameInfos() { + mStatus = 0; + mLabels = new CharSequence[FolderNameProvider.SUGGEST_MAX]; + mScores = new Float[FolderNameProvider.SUGGEST_MAX]; + } + + /** + * set the status of FolderNameInfos. + */ + public void setStatus(int statusBit) { + mStatus = mStatus | statusBit; + } + + /** + * returns status of FolderNameInfos generations. + */ + public int status() { + return mStatus; + } + + /** + * return true if the first suggestion is a Primary suggestion. + */ + public boolean hasPrimary() { + return (mStatus & HAS_PRIMARY) > 0 && (mLabels[0] != null); + } + + /** + * return true if there is at least one valid suggestion. + */ + public boolean hasSuggestions() { + for (CharSequence l : mLabels) { + if (l != null && !TextUtils.isEmpty(l)) return true; + } + return false; + } + + /** + * assign label and score in the specified index. + */ + public void setLabel(int index, CharSequence label, Float score) { + if (index < mLabels.length) { + mLabels[index] = label; + mScores[index] = score; + } + } + + /** + * returns true if the label is found in label suggestions/ + */ + public boolean contains(CharSequence label) { + return Arrays.stream(mLabels) + .filter(Objects::nonNull) + .anyMatch(l -> l.toString().equalsIgnoreCase(label.toString())); + } + + + public CharSequence[] getLabels() { + return mLabels; + } + + public Float[] getScores() { + return mScores; + } + + @Override + @NonNull + public String toString() { + return String.format("status=%s, labels=%s", Integer.toBinaryString(mStatus), + Arrays.toString(mLabels)); + } +} + diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java index 2be0bcee17..d166e27c23 100644 --- a/src/com/android/launcher3/folder/FolderNameProvider.java +++ b/src/com/android/launcher3/folder/FolderNameProvider.java @@ -96,10 +96,10 @@ public class FolderNameProvider implements ResourceBasedOverride { */ public void getSuggestedFolderName(Context context, ArrayList workspaceItemInfos, - FolderNameInfo[] nameInfos) { + FolderNameInfos nameInfos) { Preconditions.assertWorkerThread(); if (DEBUG) { - Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(nameInfos)); + Log.d(TAG, "getSuggestedFolderName:" + nameInfos.toString()); } // If all the icons are from work profile, // Then, suggest "Work" as the folder name @@ -124,7 +124,7 @@ public class FolderNameProvider implements ResourceBasedOverride { info.ifPresent(i -> setAsFirstSuggestion(nameInfos, i.title.toString())); } if (DEBUG) { - Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(nameInfos)); + Log.d(TAG, "getSuggestedFolderName:" + nameInfos.toString()); } } @@ -138,39 +138,37 @@ public class FolderNameProvider implements ResourceBasedOverride { .findAny(); } - private void setAsFirstSuggestion(FolderNameInfo[] nameInfos, CharSequence label) { - if (nameInfos.length == 0 || contains(nameInfos, label)) { + private void setAsFirstSuggestion(FolderNameInfos nameInfos, CharSequence label) { + if (nameInfos == null || nameInfos.contains(label)) { return; } - for (int i = nameInfos.length - 1; i > 0; i--) { - if (nameInfos[i - 1] != null && !TextUtils.isEmpty(nameInfos[i - 1].getLabel())) { - nameInfos[i] = nameInfos[i - 1]; + nameInfos.setStatus(FolderNameInfos.HAS_PRIMARY); + nameInfos.setStatus(FolderNameInfos.HAS_SUGGESTIONS); + CharSequence[] labels = nameInfos.getLabels(); + Float[] scores = nameInfos.getScores(); + for (int i = labels.length - 1; i > 0; i--) { + if (labels[i - 1] != null && !TextUtils.isEmpty(labels[i - 1])) { + nameInfos.setLabel(i, labels[i - 1], scores[i - 1]); } } - nameInfos[0] = new FolderNameInfo(label, 1.0); + nameInfos.setLabel(0, label, 1.0f); } - private void setAsLastSuggestion(FolderNameInfo[] nameInfos, CharSequence label) { - if (nameInfos.length == 0 || contains(nameInfos, label)) { + private void setAsLastSuggestion(FolderNameInfos nameInfos, CharSequence label) { + if (nameInfos == null || nameInfos.contains(label)) { return; } - - for (int i = 0; i < nameInfos.length; i++) { - if (nameInfos[i] == null || TextUtils.isEmpty(nameInfos[i].getLabel())) { - nameInfos[i] = new FolderNameInfo(label, 1.0); + nameInfos.setStatus(FolderNameInfos.HAS_PRIMARY); + nameInfos.setStatus(FolderNameInfos.HAS_SUGGESTIONS); + CharSequence[] labels = nameInfos.getLabels(); + for (int i = 0; i < labels.length; i++) { + if (labels[i] == null || TextUtils.isEmpty(labels[i])) { + nameInfos.setLabel(i, label, 1.0f); return; } } // Overwrite the last suggestion. - int lastIndex = nameInfos.length - 1; - nameInfos[lastIndex] = new FolderNameInfo(label, 1.0); - } - - private boolean contains(FolderNameInfo[] nameInfos, CharSequence label) { - return Arrays.stream(nameInfos) - .filter(Objects::nonNull) - .anyMatch(nameInfo -> nameInfo.getLabel().toString().equalsIgnoreCase( - label.toString())); + nameInfos.setLabel(labels.length - 1, label, 1.0f); } private class FolderNameWorker extends BaseModelUpdateTask { diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index f2073ef245..102ec31e1c 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -59,7 +59,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderGridOrganizer; -import com.android.launcher3.folder.FolderNameInfo; +import com.android.launcher3.folder.FolderNameInfos; import com.android.launcher3.folder.FolderNameProvider; import com.android.launcher3.icons.ComponentWithLabelAndIcon; import com.android.launcher3.icons.ComponentWithLabelAndIcon.ComponentWithIconCachingLogic; @@ -953,13 +953,12 @@ public class LoaderTask implements Runnable { synchronized (mBgDataModel) { for (int i = 0; i < mBgDataModel.folders.size(); i++) { - FolderNameInfo[] suggestionInfos = - new FolderNameInfo[FolderNameProvider.SUGGEST_MAX]; + FolderNameInfos suggestionInfos = new FolderNameInfos(); FolderInfo info = mBgDataModel.folders.valueAt(i); if (info.suggestedFolderNames == null) { provider.getSuggestedFolderName(mApp.getContext(), info.contents, suggestionInfos); - info.suggestedFolderNames = new Intent().putExtra("suggest", suggestionInfos); + info.suggestedFolderNames = suggestionInfos; } } } diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java index 08eb3831a0..ecd18ce268 100644 --- a/src/com/android/launcher3/model/data/FolderInfo.java +++ b/src/com/android/launcher3/model/data/FolderInfo.java @@ -29,17 +29,12 @@ import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolder import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_FOLDER_LABEL_STATE_UNSPECIFIED; import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_SUGGESTED; -import static java.util.Arrays.stream; -import static java.util.Optional.ofNullable; - -import android.content.Intent; import android.os.Process; -import android.text.TextUtils; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.folder.FolderNameInfo; +import com.android.launcher3.folder.FolderNameInfos; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logger.LauncherAtom.FromState; import com.android.launcher3.logger.LauncherAtom.ToState; @@ -51,8 +46,6 @@ import com.android.launcher3.userevent.LauncherLogProto.Target.ToFolderLabelStat import com.android.launcher3.util.ContentWriter; import java.util.ArrayList; -import java.util.Objects; -import java.util.Optional; import java.util.OptionalInt; import java.util.stream.IntStream; @@ -85,7 +78,7 @@ public class FolderInfo extends ItemInfo { public int options; - public Intent suggestedFolderNames; + public FolderNameInfos suggestedFolderNames; /** * The apps and shortcuts @@ -224,17 +217,16 @@ public class FolderInfo extends ItemInfo { public OptionalInt getAcceptedSuggestionIndex() { String newLabel = checkNotNull(title, "Expected valid folder label, but found null").toString(); - return getSuggestedLabels() - .map(suggestionsArray -> - IntStream.range(0, suggestionsArray.length) - .filter( - index -> !isEmpty(suggestionsArray[index]) - && newLabel.equalsIgnoreCase( - suggestionsArray[index])) - .sequential() - .findFirst() - ).orElse(OptionalInt.empty()); - + if (suggestedFolderNames == null || !suggestedFolderNames.hasSuggestions()) { + return OptionalInt.empty(); + } + CharSequence[] labels = suggestedFolderNames.getLabels(); + return IntStream.range(0, labels.length) + .filter(index -> !isEmpty(labels[index]) + && newLabel.equalsIgnoreCase( + labels[index].toString())) + .sequential() + .findFirst(); } /** @@ -264,19 +256,15 @@ public class FolderInfo extends ItemInfo { : LauncherAtom.ToState.TO_EMPTY_WITH_SUGGESTIONS_DISABLED; } - Optional suggestedLabels = getSuggestedLabels(); - boolean isEmptySuggestions = suggestedLabels - .map(labels -> stream(labels).allMatch(TextUtils::isEmpty)) - .orElse(true); - if (isEmptySuggestions) { + // TODO: if suggestedFolderNames is null then it infrastructure issue, not + // ranking issue. We should log these appropriately. + if (suggestedFolderNames == null || !suggestedFolderNames.hasSuggestions()) { return title.length() > 0 ? LauncherAtom.ToState.TO_CUSTOM_WITH_EMPTY_SUGGESTIONS : LauncherAtom.ToState.TO_EMPTY_WITH_EMPTY_SUGGESTIONS; } - boolean hasValidPrimary = suggestedLabels - .map(labels -> !isEmpty(labels[0])) - .orElse(false); + boolean hasValidPrimary = suggestedFolderNames != null && suggestedFolderNames.hasPrimary(); if (title.length() == 0) { return hasValidPrimary ? LauncherAtom.ToState.TO_EMPTY_WITH_VALID_PRIMARY : LauncherAtom.ToState.TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY; @@ -306,20 +294,6 @@ public class FolderInfo extends ItemInfo { return LauncherAtom.ToState.TO_STATE_UNSPECIFIED; } - private Optional getSuggestedLabels() { - return ofNullable(suggestedFolderNames) - .map(folderNames -> - (FolderNameInfo[]) - folderNames.getParcelableArrayExtra(EXTRA_FOLDER_SUGGESTIONS)) - .map(folderNameInfoArray -> - stream(folderNameInfoArray) - .filter(Objects::nonNull) - .map(FolderNameInfo::getLabel) - .filter(Objects::nonNull) - .map(CharSequence::toString) - .toArray(String[]::new)); - } - /** * Returns {@link LauncherLogProto.LauncherEvent} to log current folder label info. *