Move probability updating during GC to PtNodeWriter.

Bug: 11073222

Change-Id: Id452f953c4f72c4e83f6866a87be5f3766d00a31
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
index 5c6a365..84dd687 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/pt_common/pt_node_writer.h
@@ -54,6 +54,10 @@
     virtual bool updatePtNodeProbability(const PtNodeParams *const toBeUpdatedPtNodeParams,
             const int probability, const int timestamp) = 0;
 
+    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+            const PtNodeParams *const toBeUpdatedPtNodeParams,
+            bool *const outNeedsToKeepPtNode) = 0;
+
     virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
                 const int newChildrenPosition) = 0;
 
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.cpp
index a06962e..d417535 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v3/dynamic_patricia_trie_gc_event_listeners.cpp
@@ -30,22 +30,16 @@
     // PtNode is useless when the PtNode is not a terminal and doesn't have any not useless
     // children.
     bool isUselessPtNode = !ptNodeParams->isTerminal();
+    // TODO: Quit checking mNeedsToDecayWhenUpdating.
     if (ptNodeParams->isTerminal() && mNeedsToDecayWhenUpdating) {
-        // TODO: Avoid decaying probability during GC.
-        const int newProbability =
-                ForgettingCurveUtils::getEncodedProbabilityToSave(ptNodeParams->getProbability(),
-                        mHeaderPolicy);
-        // Update probability.
-        if (!mPtNodeWriter->updatePtNodeProbability(ptNodeParams, newProbability,
-                0 /* timestamp */)) {
+        bool needsToKeepPtNode = true;
+        if (!mPtNodeWriter->updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(ptNodeParams,
+                &needsToKeepPtNode)) {
+            AKLOGE("Cannot update PtNode probability or get needs to keep PtNode after GC.");
             return false;
         }
-        if (!ForgettingCurveUtils::isValidEncodedProbability(newProbability)) {
+        if (!needsToKeepPtNode) {
             isUselessPtNode = true;
-            if (!mPtNodeWriter->markPtNodeAsWillBecomeNonTerminal(ptNodeParams)) {
-                AKLOGE("Cannot mark PtNode as willBecomeNonTerminal.");
-                return false;
-            }
         }
     }
     if (mChildrenValue > 0) {
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
index 2a9acf5..867cd76 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.cpp
@@ -141,6 +141,42 @@
             toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry);
 }
 
+bool Ver4PatriciaTrieNodeWriter::updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+        const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode) {
+    if (!toBeUpdatedPtNodeParams->isTerminal()) {
+        AKLOGE("updatePtNodeProbabilityAndGetNeedsToSaveForGC is called for non-terminal PtNode.");
+        return false;
+    }
+    if (mBuffers->getHeaderPolicy()->isDecayingDict()) {
+        const ProbabilityEntry originalProbabilityEntry =
+                mBuffers->getProbabilityDictContent()->getProbabilityEntry(
+                        toBeUpdatedPtNodeParams->getTerminalId());
+        // TODO: Use historical info.
+        const int newProbability = ForgettingCurveUtils::getEncodedProbabilityToSave(
+                originalProbabilityEntry.getProbability(), mBuffers->getHeaderPolicy());
+        const ProbabilityEntry probabilityEntry =
+                originalProbabilityEntry.createEntryWithUpdatedProbability(newProbability);
+        if (!mBuffers->getMutableProbabilityDictContent()->setProbabilityEntry(
+                toBeUpdatedPtNodeParams->getTerminalId(), &probabilityEntry)) {
+            AKLOGE("Cannot write updated probability entry. terminalId: %d",
+                    toBeUpdatedPtNodeParams->getTerminalId());
+            return false;
+        }
+        const bool isValid = ForgettingCurveUtils::isValidEncodedProbability(newProbability);
+        if (!isValid) {
+            if (!markPtNodeAsWillBecomeNonTerminal(toBeUpdatedPtNodeParams)) {
+                AKLOGE("Cannot mark PtNode as willBecomeNonTerminal.");
+                return false;
+            }
+        }
+        *outNeedsToKeepPtNode = isValid;
+    } else {
+        // No need to update probability.
+        *outNeedsToKeepPtNode = true;
+    }
+    return true;
+}
+
 bool Ver4PatriciaTrieNodeWriter::updateChildrenPosition(
         const PtNodeParams *const toBeUpdatedPtNodeParams, const int newChildrenPosition) {
     int childrenPosFieldPos = toBeUpdatedPtNodeParams->getChildrenPosFieldPos();
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
index cc66688..b0b5b70 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_node_writer.h
@@ -60,6 +60,9 @@
     virtual bool updatePtNodeProbability(const PtNodeParams *const toBeUpdatedPtNodeParams,
             const int newProbability, const int timestamp);
 
+    virtual bool updatePtNodeProbabilityAndGetNeedsToKeepPtNodeAfterGC(
+            const PtNodeParams *const toBeUpdatedPtNodeParams, bool *const outNeedsToKeepPtNode);
+
     virtual bool updateChildrenPosition(const PtNodeParams *const toBeUpdatedPtNodeParams,
             const int newChildrenPosition);