1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.textclassifier.common.statsd; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.view.textclassifier.SelectionEvent; 22 import android.view.textclassifier.TextClassification; 23 import android.view.textclassifier.TextClassificationContext; 24 import android.view.textclassifier.TextClassificationManager; 25 import android.view.textclassifier.TextClassifier; 26 import android.view.textclassifier.TextClassifierEvent; 27 import android.view.textclassifier.TextSelection; 28 import androidx.test.core.app.ApplicationProvider; 29 import androidx.test.ext.junit.runners.AndroidJUnit4; 30 import androidx.test.filters.SmallTest; 31 import com.android.textclassifier.common.logging.ResultIdUtils; 32 import com.android.textclassifier.common.logging.ResultIdUtils.ModelInfo; 33 import com.google.common.base.Optional; 34 import com.google.common.collect.ImmutableList; 35 import java.util.ArrayDeque; 36 import java.util.Deque; 37 import java.util.Locale; 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 42 @SmallTest 43 @RunWith(AndroidJUnit4.class) 44 public class SelectionEventConverterTest { 45 private static final String PKG_NAME = "com.pkg"; 46 private static final String WIDGET_TYPE = TextClassifier.WIDGET_TYPE_EDITTEXT; 47 private static final int START = 2; 48 private static final int SMART_START = 1; 49 private static final int SMART_END = 3; 50 private TestTextClassifier testTextClassifier; 51 private TextClassifier session; 52 53 @Before setup()54 public void setup() { 55 TextClassificationManager textClassificationManager = 56 ApplicationProvider.getApplicationContext() 57 .getSystemService(TextClassificationManager.class); 58 testTextClassifier = new TestTextClassifier(); 59 textClassificationManager.setTextClassifier(testTextClassifier); 60 session = textClassificationManager.createTextClassificationSession(createEventContext()); 61 } 62 63 @Test convert_started()64 public void convert_started() { 65 session.onSelectionEvent( 66 SelectionEvent.createSelectionStartedEvent(SelectionEvent.INVOCATION_MANUAL, START)); 67 68 SelectionEvent interceptedEvent = testTextClassifier.popLastSelectionEvent(); 69 TextClassifierEvent textClassifierEvent = 70 SelectionEventConverter.toTextClassifierEvent(interceptedEvent); 71 72 assertEventContext(textClassifierEvent.getEventContext()); 73 assertThat(textClassifierEvent.getEventIndex()).isEqualTo(0); 74 assertThat(textClassifierEvent.getEventType()) 75 .isEqualTo(TextClassifierEvent.TYPE_SELECTION_STARTED); 76 } 77 78 @Test convert_smartSelection()79 public void convert_smartSelection() { 80 session.onSelectionEvent( 81 SelectionEvent.createSelectionStartedEvent(SelectionEvent.INVOCATION_MANUAL, START)); 82 String resultId = createResultId(); 83 session.onSelectionEvent( 84 SelectionEvent.createSelectionActionEvent( 85 SMART_START, 86 SMART_END, 87 SelectionEvent.ACTION_SMART_SHARE, 88 new TextClassification.Builder() 89 .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f) 90 .setId(resultId) 91 .build())); 92 93 SelectionEvent interceptedEvent = testTextClassifier.popLastSelectionEvent(); 94 TextClassifierEvent.TextSelectionEvent textSelectionEvent = 95 (TextClassifierEvent.TextSelectionEvent) 96 SelectionEventConverter.toTextClassifierEvent(interceptedEvent); 97 98 assertEventContext(textSelectionEvent.getEventContext()); 99 assertThat(textSelectionEvent.getRelativeWordStartIndex()).isEqualTo(-1); 100 assertThat(textSelectionEvent.getRelativeWordEndIndex()).isEqualTo(1); 101 assertThat(textSelectionEvent.getEventType()).isEqualTo(TextClassifierEvent.TYPE_SMART_ACTION); 102 assertThat(textSelectionEvent.getEventIndex()).isEqualTo(1); 103 assertThat(textSelectionEvent.getEntityTypes()) 104 .asList() 105 .containsExactly(TextClassifier.TYPE_ADDRESS); 106 assertThat(textSelectionEvent.getResultId()).isEqualTo(resultId); 107 } 108 109 @Test convert_smartShare()110 public void convert_smartShare() { 111 session.onSelectionEvent( 112 SelectionEvent.createSelectionStartedEvent(SelectionEvent.INVOCATION_MANUAL, START)); 113 String resultId = createResultId(); 114 session.onSelectionEvent( 115 SelectionEvent.createSelectionModifiedEvent( 116 SMART_START, 117 SMART_END, 118 new TextSelection.Builder(SMART_START, SMART_END) 119 .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f) 120 .setId(resultId) 121 .build())); 122 123 SelectionEvent interceptedEvent = testTextClassifier.popLastSelectionEvent(); 124 TextClassifierEvent.TextSelectionEvent textSelectionEvent = 125 (TextClassifierEvent.TextSelectionEvent) 126 SelectionEventConverter.toTextClassifierEvent(interceptedEvent); 127 128 assertEventContext(textSelectionEvent.getEventContext()); 129 assertThat(textSelectionEvent.getRelativeSuggestedWordStartIndex()).isEqualTo(-1); 130 assertThat(textSelectionEvent.getRelativeSuggestedWordEndIndex()).isEqualTo(1); 131 assertThat(textSelectionEvent.getEventType()) 132 .isEqualTo(TextClassifierEvent.TYPE_SMART_SELECTION_MULTI); 133 assertThat(textSelectionEvent.getEventIndex()).isEqualTo(1); 134 assertThat(textSelectionEvent.getEntityTypes()) 135 .asList() 136 .containsExactly(TextClassifier.TYPE_ADDRESS); 137 assertThat(textSelectionEvent.getResultId()).isEqualTo(resultId); 138 } 139 140 @Test convert_smartLinkify()141 public void convert_smartLinkify() { 142 session.onSelectionEvent( 143 SelectionEvent.createSelectionStartedEvent(SelectionEvent.INVOCATION_LINK, START)); 144 String resultId = createResultId(); 145 session.onSelectionEvent( 146 SelectionEvent.createSelectionModifiedEvent( 147 SMART_START, 148 SMART_END, 149 new TextSelection.Builder(SMART_START, SMART_END) 150 .setEntityType(TextClassifier.TYPE_ADDRESS, 1.0f) 151 .setId(resultId) 152 .build())); 153 154 SelectionEvent interceptedEvent = testTextClassifier.popLastSelectionEvent(); 155 TextClassifierEvent.TextLinkifyEvent textLinkifyEvent = 156 (TextClassifierEvent.TextLinkifyEvent) 157 SelectionEventConverter.toTextClassifierEvent(interceptedEvent); 158 159 assertEventContext(textLinkifyEvent.getEventContext()); 160 assertThat(textLinkifyEvent.getEventType()) 161 .isEqualTo(TextClassifierEvent.TYPE_SMART_SELECTION_MULTI); 162 assertThat(textLinkifyEvent.getEventIndex()).isEqualTo(1); 163 assertThat(textLinkifyEvent.getEntityTypes()) 164 .asList() 165 .containsExactly(TextClassifier.TYPE_ADDRESS); 166 assertThat(textLinkifyEvent.getResultId()).isEqualTo(resultId); 167 } 168 createEventContext()169 private static TextClassificationContext createEventContext() { 170 return new TextClassificationContext.Builder(PKG_NAME, TextClassifier.WIDGET_TYPE_EDITTEXT) 171 .build(); 172 } 173 assertEventContext(TextClassificationContext eventContext)174 private static void assertEventContext(TextClassificationContext eventContext) { 175 assertThat(eventContext.getPackageName()).isEqualTo(PKG_NAME); 176 assertThat(eventContext.getWidgetType()).isEqualTo(WIDGET_TYPE); 177 } 178 createResultId()179 private static String createResultId() { 180 return ResultIdUtils.createId( 181 /*hash=*/ 12345, 182 ImmutableList.of( 183 Optional.of(new ModelInfo(/* version= */ 702, ImmutableList.of(Locale.ENGLISH))))); 184 } 185 186 private static class TestTextClassifier implements TextClassifier { 187 private final Deque<SelectionEvent> selectionEvents = new ArrayDeque<>(); 188 189 @Override onSelectionEvent(SelectionEvent event)190 public void onSelectionEvent(SelectionEvent event) { 191 selectionEvents.push(event); 192 } 193 popLastSelectionEvent()194 SelectionEvent popLastSelectionEvent() { 195 return selectionEvents.pop(); 196 } 197 } 198 } 199