Merge "Add new FolderLabelStates to better understand smart folder acceptance rate based on primary suggestion." into ub-launcher3-master
diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto
index 0fe5310..9423cb2 100644
--- a/protos/launcher_log.proto
+++ b/protos/launcher_log.proto
@@ -63,14 +63,14 @@
 
   // Note: proto does not support duplicate enum values, even if they belong to different enum type.
   // Hence "FROM" and "TO" prefix added.
-  enum FromFolderLabelState{
+  enum FromFolderLabelState {
     FROM_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
     FROM_EMPTY = 1;
     FROM_CUSTOM = 2;
     FROM_SUGGESTED = 3;
   }
 
-  enum ToFolderLabelState{
+  enum ToFolderLabelState {
     TO_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
     TO_SUGGESTION0_WITH_VALID_PRIMARY = 1;
     TO_SUGGESTION1_WITH_VALID_PRIMARY = 2;
@@ -79,10 +79,14 @@
     TO_SUGGESTION2_WITH_EMPTY_PRIMARY = 5;
     TO_SUGGESTION3_WITH_VALID_PRIMARY = 6;
     TO_SUGGESTION3_WITH_EMPTY_PRIMARY = 7;
-    TO_EMPTY_WITH_VALID_SUGGESTIONS = 8;
+    TO_EMPTY_WITH_VALID_SUGGESTIONS = 8 [deprecated = true];
+    TO_EMPTY_WITH_VALID_PRIMARY = 15;
+    TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 16;
     TO_EMPTY_WITH_EMPTY_SUGGESTIONS = 9;
     TO_EMPTY_WITH_SUGGESTIONS_DISABLED = 10;
-    TO_CUSTOM_WITH_VALID_SUGGESTIONS = 11;
+    TO_CUSTOM_WITH_VALID_SUGGESTIONS = 11 [deprecated = true];
+    TO_CUSTOM_WITH_VALID_PRIMARY = 17;
+    TO_CUSTOM_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 18;
     TO_CUSTOM_WITH_EMPTY_SUGGESTIONS = 12;
     TO_CUSTOM_WITH_SUGGESTIONS_DISABLED = 13;
     UNCHANGED = 14;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 202836d..ea7317a 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -98,6 +98,7 @@
 import com.android.launcher3.userevent.LauncherLogProto.ItemType;
 import com.android.launcher3.userevent.LauncherLogProto.LauncherEvent;
 import com.android.launcher3.userevent.LauncherLogProto.Target;
+import com.android.launcher3.userevent.LauncherLogProto.Target.ToFolderLabelState;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.Thunk;
@@ -110,6 +111,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.OptionalInt;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -346,7 +348,7 @@
         }
 
         mInfo.title = newTitle;
-        mInfo.setOption(FLAG_MANUAL_FOLDER_NAME, getAcceptedSuggestionIndex() < 0,
+        mInfo.setOption(FLAG_MANUAL_FOLDER_NAME, !getAcceptedSuggestionIndex().isPresent(),
                 mLauncher.getModelWriter());
         mFolderIcon.onTitleChanged(newTitle);
         mLauncher.getModelWriter().updateItemInDatabase(mInfo);
@@ -1679,36 +1681,58 @@
     private Target.ToFolderLabelState getToFolderLabelState() {
         String newLabel =
                 checkNotNull(mFolderName.getText().toString(),
-                        "Expected valid folder label, but found null");
+                "Expected valid folder label, but found null");
+        if (newLabel.equals(mPreviousLabel)) {
+            return Target.ToFolderLabelState.UNCHANGED;
+        }
+
+        if (!FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
+            return newLabel.isEmpty()
+                ? ToFolderLabelState.TO_EMPTY_WITH_SUGGESTIONS_DISABLED
+                : ToFolderLabelState.TO_CUSTOM_WITH_SUGGESTIONS_DISABLED;
+        }
 
         Optional<String[]> suggestedLabels = getSuggestedLabels();
-        int accepted_suggestion_index = getAcceptedSuggestionIndex();
-        boolean hasValidPrimary = suggestedLabels
-                .map(labels -> labels.length > 0 && !isEmpty(labels[0]))
-                .orElse(false);
-        String primarySuffix = hasValidPrimary
-                ? "_WITH_VALID_PRIMARY"
-                : "_WITH_EMPTY_PRIMARY";
-
         boolean isEmptySuggestions = suggestedLabels
                 .map(labels -> stream(labels).allMatch(TextUtils::isEmpty))
                 .orElse(true);
-        boolean isSuggestionsEnabled = FeatureFlags.FOLDER_NAME_SUGGEST.get();
-        String suggestionsSuffix =  isSuggestionsEnabled
-                ? isEmptySuggestions
-                    ? "_WITH_EMPTY_SUGGESTIONS"
-                    : "_WITH_VALID_SUGGESTIONS"
-                : "_WITH_SUGGESTIONS_DISABLED";
+        if (isEmptySuggestions) {
+            return newLabel.isEmpty()
+                ? ToFolderLabelState.TO_EMPTY_WITH_EMPTY_SUGGESTIONS
+                : ToFolderLabelState.TO_CUSTOM_WITH_EMPTY_SUGGESTIONS;
+        }
 
-        return newLabel.equals(mPreviousLabel)
-                ? Target.ToFolderLabelState.UNCHANGED
-                : newLabel.isEmpty()
-                    ? Target.ToFolderLabelState.valueOf("TO_EMPTY" + suggestionsSuffix)
-                    : accepted_suggestion_index >= 0
-                        ? Target.ToFolderLabelState.valueOf("TO_SUGGESTION"
-                            + accepted_suggestion_index
-                            + primarySuffix)
-                        : Target.ToFolderLabelState.valueOf("TO_CUSTOM" + suggestionsSuffix);
+        boolean hasValidPrimary = suggestedLabels
+                .map(labels -> !isEmpty(labels[0]))
+                .orElse(false);
+        if (newLabel.isEmpty()) {
+            return hasValidPrimary ? ToFolderLabelState.TO_EMPTY_WITH_VALID_PRIMARY
+                : ToFolderLabelState.TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY;
+        }
+
+        OptionalInt accepted_suggestion_index = getAcceptedSuggestionIndex();
+        if (!accepted_suggestion_index.isPresent()) {
+            return hasValidPrimary ? ToFolderLabelState.TO_CUSTOM_WITH_VALID_PRIMARY
+                : ToFolderLabelState.TO_CUSTOM_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY;
+        }
+
+        switch (accepted_suggestion_index.getAsInt()) {
+            case 0:
+                return ToFolderLabelState.TO_SUGGESTION0_WITH_VALID_PRIMARY;
+            case 1:
+                return hasValidPrimary ? ToFolderLabelState.TO_SUGGESTION1_WITH_VALID_PRIMARY
+                    : ToFolderLabelState.TO_SUGGESTION1_WITH_EMPTY_PRIMARY;
+            case 2:
+                return hasValidPrimary ? ToFolderLabelState.TO_SUGGESTION2_WITH_VALID_PRIMARY
+                    : ToFolderLabelState.TO_SUGGESTION2_WITH_EMPTY_PRIMARY;
+            case 3:
+                return hasValidPrimary ? ToFolderLabelState.TO_SUGGESTION3_WITH_VALID_PRIMARY
+                    : ToFolderLabelState.TO_SUGGESTION3_WITH_EMPTY_PRIMARY;
+            default:
+                // fall through
+        }
+        return ToFolderLabelState.TO_FOLDER_LABEL_STATE_UNSPECIFIED;
+
     }
 
     private Optional<String[]> getSuggestedLabels() {
@@ -1728,19 +1752,18 @@
                         .toArray(String[]::new));
     }
 
-    private int getAcceptedSuggestionIndex() {
-        String newLabel =
-                checkNotNull(mFolderName.getText().toString(),
-                        "Expected valid folder label, but found null");
-
+    private OptionalInt getAcceptedSuggestionIndex() {
+        String newLabel = checkNotNull(mFolderName.getText().toString(),
+                "Expected valid folder label, but found null");
         return getSuggestedLabels()
                 .map(suggestionsArray ->
-                        IntStream.range(0, suggestionsArray.length)
-                                .filter(index -> newLabel.equalsIgnoreCase(
-                                        suggestionsArray[index]))
-                                .findFirst()
-                                .orElse(-1)
-                ).orElse(-1);
+                    IntStream.range(0, suggestionsArray.length)
+                        .filter(
+                            index -> !isEmpty(suggestionsArray[index])
+                                && newLabel.equalsIgnoreCase(suggestionsArray[index]))
+                        .sequential()
+                        .findFirst()
+                ).orElse(OptionalInt.empty());
 
     }
 
@@ -1761,7 +1784,6 @@
 
     private Target.Builder newParentContainerTarget() {
         Target.Builder builder = Target.newBuilder().setType(Target.Type.CONTAINER);
-
         switch (mInfo.container) {
             case CONTAINER_HOTSEAT:
                 return builder.setContainerType(ContainerType.HOTSEAT);