Export libtextclassifier am: 3f7c560ea8 am: bcc67c3eee

Change-Id: I23c1b172ed0309b20cde2fb54b19cd60a4ef59b1
diff --git a/notification/src/com/android/textclassifier/notification/SmartSuggestionsHelper.java b/notification/src/com/android/textclassifier/notification/SmartSuggestionsHelper.java
index fab0dd1..a6aa9ae 100644
--- a/notification/src/com/android/textclassifier/notification/SmartSuggestionsHelper.java
+++ b/notification/src/com/android/textclassifier/notification/SmartSuggestionsHelper.java
@@ -83,7 +83,16 @@
   private final TextClassificationManager textClassificationManager;
   private final SmartSuggestionsConfig config;
   private final LruCache<String, SmartSuggestionsLogSession> sessionCache =
-      new LruCache<>(MAX_RESULT_ID_TO_CACHE);
+      new LruCache<String, SmartSuggestionsLogSession>(MAX_RESULT_ID_TO_CACHE) {
+        @Override
+        protected void entryRemoved(
+            boolean evicted,
+            String key,
+            SmartSuggestionsLogSession oldSession,
+            SmartSuggestionsLogSession newSession) {
+          oldSession.destroy();
+        }
+      };
   private final TextClassificationContext textClassificationContext;
 
   public SmartSuggestionsHelper(Context context, SmartSuggestionsConfig config) {
@@ -103,7 +112,7 @@
   public SmartSuggestions onNotificationEnqueued(StatusBarNotification statusBarNotification) {
     // Whenever onNotificationEnqueued() is called again on the same notification key, its
     // previous session is ended.
-    removeAndDestroySession(statusBarNotification.getKey());
+    sessionCache.remove(statusBarNotification.getKey());
 
     boolean eligibleForReplyAdjustment =
         config.shouldGenerateReplies() && isEligibleForReplyAdjustment(statusBarNotification);
@@ -155,8 +164,9 @@
         actions.add(notificationAction);
       }
     }
-
-    if (!TextUtils.isEmpty(resultId)) {
+    if (TextUtils.isEmpty(resultId)) {
+      textClassifier.destroy();
+    } else {
       SmartSuggestionsLogSession session =
           new SmartSuggestionsLogSession(
               resultId, repliesScore, textClassifier, textClassificationContext);
@@ -175,14 +185,6 @@
     return new SmartSuggestions(replies, actions);
   }
 
-  private void removeAndDestroySession(String notificationKey) {
-    SmartSuggestionsLogSession session = sessionCache.get(notificationKey);
-    if (session != null) {
-      session.destroy();
-    }
-    sessionCache.remove(notificationKey);
-  }
-
   /**
    * Creates notification action from ConversationAction that does not come up a RemoteAction. It
    * could happen because we don't have common intents for some actions, like copying text.
diff --git a/notification/tests/src/com/android/textclassifier/notification/SmartSuggestionsHelperTest.java b/notification/tests/src/com/android/textclassifier/notification/SmartSuggestionsHelperTest.java
index bc10cc0..1cbfbf2 100644
--- a/notification/tests/src/com/android/textclassifier/notification/SmartSuggestionsHelperTest.java
+++ b/notification/tests/src/com/android/textclassifier/notification/SmartSuggestionsHelperTest.java
@@ -47,6 +47,7 @@
 import java.util.Collection;
 import java.util.List;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -71,10 +72,6 @@
   public void setup() {
     TextClassificationManager textClassificationManager =
         context.getSystemService(TextClassificationManager.class);
-    // Workaround b/144163980.
-    // TODO(tonymak) Remove this workaround once the latest emulator image is dropped.
-    textClassificationManager.setTextClassificationSessionFactory(
-        classificationContext -> fakeTextClassifier);
     textClassificationManager.setTextClassifier(fakeTextClassifier);
     smartActions = new SmartSuggestionsHelper(context, config);
     notificationBuilder = new Notification.Builder(context, "id");
@@ -345,6 +342,25 @@
     assertThat(smartSuggestions.getActions().get(0).title.toString()).isEqualTo("12345");
   }
 
+  @Ignore // Disabled because it is way too slow to run on an emulator.
+  @Test
+  public void noBinderLeakage() {
+    // Use the real text classifier from system.
+    TextClassificationManager textClassificationManager =
+        context.getSystemService(TextClassificationManager.class);
+    textClassificationManager.setTextClassifier(null);
+
+    // System server crashes when there are more than 20,000 leaked binder proxy.
+    // See
+    // http://cs/android/frameworks/base/core/java/android/os/BinderProxy.java?l=73&rcl=ae52315c8c7d0391bd3c7bca0525a98eeb4cd840.
+    for (int i = 0; i < 20000; i++) {
+      Notification notification = createMessageCategoryNotification();
+      StatusBarNotification statusBarNotification =
+          createStatusBarNotification(notification, PACKAGE_NAME);
+      smartActions.onNotificationEnqueued(statusBarNotification);
+    }
+  }
+
   private Notification createMessageCategoryNotification() {
     return notificationBuilder
         .setContentText(MESSAGE)