1/*
2 * Copyright (C) 2017 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
17package android.view.textclassifier;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertNotNull;
21import static org.junit.Assert.assertNull;
22
23import android.app.PendingIntent;
24import android.app.RemoteAction;
25import android.content.Context;
26import android.content.Intent;
27import android.graphics.Bitmap;
28import android.graphics.Color;
29import android.graphics.drawable.BitmapDrawable;
30import android.graphics.drawable.Drawable;
31import android.graphics.drawable.Icon;
32import android.os.LocaleList;
33import android.os.Parcel;
34import android.support.test.InstrumentationRegistry;
35import android.support.test.filters.SmallTest;
36import android.support.test.runner.AndroidJUnit4;
37import android.view.View;
38
39import org.junit.Test;
40import org.junit.runner.RunWith;
41
42import java.time.Instant;
43import java.time.ZoneId;
44import java.time.ZonedDateTime;
45import java.util.Locale;
46
47@SmallTest
48@RunWith(AndroidJUnit4.class)
49public class TextClassificationTest {
50
51    public Icon generateTestIcon(int width, int height, int colorValue) {
52        final int numPixels = width * height;
53        final int[] colors = new int[numPixels];
54        for (int i = 0; i < numPixels; ++i) {
55            colors[i] = colorValue;
56        }
57        final Bitmap bitmap = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888);
58        return Icon.createWithBitmap(bitmap);
59    }
60
61    @Test
62    public void testParcel() {
63        final Context context = InstrumentationRegistry.getTargetContext();
64        final String text = "text";
65
66        final Icon primaryIcon = generateTestIcon(576, 288, Color.BLUE);
67        final String primaryLabel = "primaryLabel";
68        final String primaryDescription = "primaryDescription";
69        final Intent primaryIntent = new Intent("primaryIntentAction");
70        final PendingIntent primaryPendingIntent = PendingIntent.getActivity(context, 0,
71                primaryIntent, 0);
72        final RemoteAction remoteAction0 = new RemoteAction(primaryIcon, primaryLabel,
73                primaryDescription, primaryPendingIntent);
74
75        final Icon secondaryIcon = generateTestIcon(32, 288, Color.GREEN);
76        final String secondaryLabel = "secondaryLabel";
77        final String secondaryDescription = "secondaryDescription";
78        final Intent secondaryIntent = new Intent("secondaryIntentAction");
79        final PendingIntent secondaryPendingIntent = PendingIntent.getActivity(context, 0,
80                secondaryIntent, 0);
81        final RemoteAction remoteAction1 = new RemoteAction(secondaryIcon, secondaryLabel,
82                secondaryDescription, secondaryPendingIntent);
83
84        final String id = "id";
85        final TextClassification reference = new TextClassification.Builder()
86                .setText(text)
87                .addAction(remoteAction0)
88                .addAction(remoteAction1)
89                .setEntityType(TextClassifier.TYPE_ADDRESS, 0.3f)
90                .setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
91                .setId(id)
92                .build();
93
94        // Parcel and unparcel
95        final Parcel parcel = Parcel.obtain();
96        reference.writeToParcel(parcel, reference.describeContents());
97        parcel.setDataPosition(0);
98        final TextClassification result = TextClassification.CREATOR.createFromParcel(parcel);
99
100        assertEquals(text, result.getText());
101        assertEquals(id, result.getId());
102        assertEquals(2, result.getActions().size());
103
104        // Primary action.
105        final RemoteAction primaryAction = result.getActions().get(0);
106        assertEquals(primaryLabel, primaryAction.getTitle());
107        assertEquals(primaryDescription, primaryAction.getContentDescription());
108        assertEquals(primaryPendingIntent, primaryAction.getActionIntent());
109
110        // Secondary action.
111        final RemoteAction secondaryAction = result.getActions().get(1);
112        assertEquals(secondaryLabel, secondaryAction.getTitle());
113        assertEquals(secondaryDescription, secondaryAction.getContentDescription());
114        assertEquals(secondaryPendingIntent, secondaryAction.getActionIntent());
115
116        // Entities.
117        assertEquals(2, result.getEntityCount());
118        assertEquals(TextClassifier.TYPE_PHONE, result.getEntity(0));
119        assertEquals(TextClassifier.TYPE_ADDRESS, result.getEntity(1));
120        assertEquals(0.7f, result.getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
121        assertEquals(0.3f, result.getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
122    }
123
124    @Test
125    public void testParcelLegacy() {
126        final Context context = InstrumentationRegistry.getInstrumentation().getContext();
127
128        final int legacyIconWidth = 192;
129        final int legacyIconHeight = 96;
130        final int legacyIconColor = Color.BLUE;
131        final Drawable legacyIcon = generateTestIcon(
132                legacyIconWidth, legacyIconHeight, legacyIconColor)
133                .loadDrawable(context);
134        final String legacyLabel = "legacyLabel";
135        final Intent legacyIntent = new Intent("ACTION_LEGACY");
136        final View.OnClickListener legacyOnClick = null;
137
138        final int width = 384;
139        final int height = 192;
140        final int iconColor = Color.RED;
141        final String label = "label";
142        final PendingIntent pendingIntent = PendingIntent.getActivity(
143                context, 0, new Intent("ACTION_0"), 0);
144        final RemoteAction remoteAction = new RemoteAction(
145                generateTestIcon(width, height, iconColor),
146                label,
147                "description",
148                pendingIntent);
149
150        final TextClassification reference = new TextClassification.Builder()
151                .setIcon(legacyIcon)
152                .setLabel(legacyLabel)
153                .setIntent(legacyIntent)
154                .setOnClickListener(legacyOnClick)
155                .addAction(remoteAction)
156                .build();
157
158        // Parcel and unparcel
159        final Parcel parcel = Parcel.obtain();
160        reference.writeToParcel(parcel, reference.describeContents());
161        parcel.setDataPosition(0);
162        final TextClassification result = TextClassification.CREATOR.createFromParcel(parcel);
163
164        // Legacy fields excluding legacyIntent are replaced by first remoteAction.
165        assertNull(result.getIntent());
166        final Bitmap resultIcon = ((BitmapDrawable) result.getIcon()).getBitmap();
167        assertEquals(iconColor, resultIcon.getPixel(0, 0));
168        assertEquals(width, resultIcon.getWidth());
169        assertEquals(height, resultIcon.getHeight());
170        assertEquals(label, result.getLabel());
171        assertNotNull(result.getOnClickListener());
172    }
173
174    @Test
175    public void testParcelParcel() {
176        final ZonedDateTime referenceTime = ZonedDateTime.ofInstant(
177                Instant.ofEpochMilli(946771200000L),  // 2000-01-02
178                ZoneId.of("UTC"));
179        final String text = "text";
180
181        final TextClassification.Request reference =
182                new TextClassification.Request.Builder(text, 0, text.length())
183                        .setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
184                        .setReferenceTime(referenceTime)
185                        .build();
186
187        // Parcel and unparcel.
188        final Parcel parcel = Parcel.obtain();
189        reference.writeToParcel(parcel, reference.describeContents());
190        parcel.setDataPosition(0);
191        final TextClassification.Request result =
192                TextClassification.Request.CREATOR.createFromParcel(parcel);
193
194        assertEquals(text, result.getText());
195        assertEquals(0, result.getStartIndex());
196        assertEquals(text.length(), result.getEndIndex());
197        assertEquals(referenceTime, result.getReferenceTime());
198        assertEquals("en-US,de-DE", result.getDefaultLocales().toLanguageTags());
199        assertEquals(referenceTime, result.getReferenceTime());
200    }
201}
202