Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d07be39 authored by Tony Mak's avatar Tony Mak
Browse files

TYPE_DATE and TYPE_DATE_TIME should be considered as the same type

To avoid confusion, we already suppress actions of the same entity type.
But from the user perspective, some entity types are really
the same thing, like TYPE_DATE and TYPE_DATE_TIME.

This is just a workaround before moving to suggestConversationActions
for smart actions. Once we have moved to it, both TYPE_DATE
and TYPE_DATE_TIME entities should be mapped to the same action type
--- OPEN_CALENDAR.

FIXES: 121200744
Test: atest EntityTypeCounterTest
Test: Try out a notification with both TYPE_DATE and TYPE_DATE_TIME
      entities, observes that both actions are not shown.

Change-Id: Id1c91bff5749c62be29a2da0cc9ed7fd8960d166
parent b29300d8
Loading
Loading
Loading
Loading
+73 −0
Original line number Original line Diff line number Diff line
/**
 * Copyright (C) 2018 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 android.ext.services.notification;

import android.annotation.NonNull;
import android.util.ArrayMap;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextLinks;

/**
 * Counts the entity types for smart actions. Some entity types are considered the same
 * type, like {@link TextClassifier#TYPE_DATE} and {@link TextClassifier#TYPE_DATE_TIME}.
 */
class EntityTypeCounter {

    private static final ArrayMap<String, String> ENTITY_TYPE_MAPPING = new ArrayMap<>();

    static {
        ENTITY_TYPE_MAPPING.put(TextClassifier.TYPE_DATE_TIME, TextClassifier.TYPE_DATE);
    }

    private final ArrayMap<String, Integer> mEntityTypeCount = new ArrayMap<>();


    void increment(@NonNull String entityType) {
        entityType = convertToBaseEntityType(entityType);
        if (mEntityTypeCount.containsKey(entityType)) {
            mEntityTypeCount.put(entityType, mEntityTypeCount.get(entityType) + 1);
        } else {
            mEntityTypeCount.put(entityType, 1);
        }
    }

    int getCount(@NonNull String entityType) {
        entityType = convertToBaseEntityType(entityType);
        return mEntityTypeCount.getOrDefault(entityType, 0);
    }

    @NonNull
    private String convertToBaseEntityType(@NonNull String entityType) {
        return ENTITY_TYPE_MAPPING.getOrDefault(entityType, entityType);
    }

    /**
     * Given the links extracted from a piece of text, returns the frequency of each entity
     * type.
     */
    @NonNull
    static EntityTypeCounter fromTextLinks(@NonNull TextLinks links) {
        EntityTypeCounter counter = new EntityTypeCounter();
        for (TextLinks.TextLink link : links.getLinks()) {
            if (link.getEntityCount() == 0) {
                continue;
            }
            String entityType = link.getEntity(0);
            counter.increment(entityType);
        }
        return counter;
    }
}
+2 −24
Original line number Original line Diff line number Diff line
@@ -26,7 +26,6 @@ import android.os.Parcelable;
import android.os.Process;
import android.os.Process;
import android.service.notification.NotificationAssistantService;
import android.service.notification.NotificationAssistantService;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.LruCache;
import android.util.LruCache;
import android.view.textclassifier.ConversationActions;
import android.view.textclassifier.ConversationActions;
import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassification;
@@ -356,7 +355,7 @@ public class SmartActionsHelper {
                                        TextClassifier.HINT_TEXT_IS_NOT_EDITABLE)))
                                        TextClassifier.HINT_TEXT_IS_NOT_EDITABLE)))
                .build();
                .build();
        TextLinks links = mTextClassifier.generateLinks(textLinksRequest);
        TextLinks links = mTextClassifier.generateLinks(textLinksRequest);
        ArrayMap<String, Integer> entityTypeFrequency = getEntityTypeFrequency(links);
        EntityTypeCounter entityTypeCounter = EntityTypeCounter.fromTextLinks(links);


        ArrayList<Notification.Action> actions = new ArrayList<>();
        ArrayList<Notification.Action> actions = new ArrayList<>();
        for (TextLinks.TextLink link : links.getLinks()) {
        for (TextLinks.TextLink link : links.getLinks()) {
@@ -364,7 +363,7 @@ public class SmartActionsHelper {
            // case where a notification contains e.g. a list of phone numbers. In such cases, the
            // case where a notification contains e.g. a list of phone numbers. In such cases, the
            // user likely wants to act on the whole list rather than an individual entity.
            // user likely wants to act on the whole list rather than an individual entity.
            if (link.getEntityCount() == 0
            if (link.getEntityCount() == 0
                    || entityTypeFrequency.get(link.getEntity(0)) != 1) {
                    || entityTypeCounter.getCount(link.getEntity(0)) != 1) {
                continue;
                continue;
            }
            }


@@ -398,25 +397,4 @@ public class SmartActionsHelper {
        }
        }
        return actions;
        return actions;
    }
    }

    /**
     * Given the links extracted from a piece of text, returns the frequency of each entity
     * type.
     */
    @NonNull
    private ArrayMap<String, Integer> getEntityTypeFrequency(@NonNull TextLinks links) {
        ArrayMap<String, Integer> entityTypeCount = new ArrayMap<>();
        for (TextLinks.TextLink link : links.getLinks()) {
            if (link.getEntityCount() == 0) {
                continue;
            }
            String entityType = link.getEntity(0);
            if (entityTypeCount.containsKey(entityType)) {
                entityTypeCount.put(entityType, entityTypeCount.get(entityType) + 1);
            } else {
                entityTypeCount.put(entityType, 1);
            }
        }
        return entityTypeCount;
    }
}
}
+58 −0
Original line number Original line Diff line number Diff line
/**
 * Copyright (C) 2018 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 android.ext.services.notification;

import static com.google.common.truth.Truth.assertThat;

import android.support.test.runner.AndroidJUnit4;
import android.view.textclassifier.TextClassifier;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class EntityTypeCounterTest {
    private EntityTypeCounter mCounter;

    @Before
    public void setup() {
        mCounter = new EntityTypeCounter();
    }

    @Test
    public void testIncrementAndGetCount() {
        mCounter.increment(TextClassifier.TYPE_URL);
        mCounter.increment(TextClassifier.TYPE_URL);
        mCounter.increment(TextClassifier.TYPE_URL);

        mCounter.increment(TextClassifier.TYPE_PHONE);
        mCounter.increment(TextClassifier.TYPE_PHONE);

        assertThat(mCounter.getCount(TextClassifier.TYPE_URL)).isEqualTo(3);
        assertThat(mCounter.getCount(TextClassifier.TYPE_PHONE)).isEqualTo(2);
        assertThat(mCounter.getCount(TextClassifier.TYPE_DATE_TIME)).isEqualTo(0);
    }

    @Test
    public void testIncrementAndGetCount_typeDateAndDateTime() {
        mCounter.increment(TextClassifier.TYPE_DATE_TIME);
        mCounter.increment(TextClassifier.TYPE_DATE);

        assertThat(mCounter.getCount(TextClassifier.TYPE_DATE_TIME)).isEqualTo(2);
        assertThat(mCounter.getCount(TextClassifier.TYPE_DATE)).isEqualTo(2);
    }
}