1 /*
2  * Copyright (C) 2008 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 android.text.method.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.fail;
22 import static org.mockito.Matchers.any;
23 import static org.mockito.Mockito.atLeastOnce;
24 import static org.mockito.Mockito.never;
25 import static org.mockito.Mockito.spy;
26 import static org.mockito.Mockito.verify;
27 
28 import android.text.Editable;
29 import android.text.Selection;
30 import android.text.Spannable;
31 import android.text.Spanned;
32 import android.text.method.DateKeyListener;
33 import android.text.method.MetaKeyKeyListener;
34 import android.view.KeyCharacterMap;
35 import android.view.KeyEvent;
36 import android.view.View;
37 import android.widget.ImageView;
38 
39 import androidx.test.filters.MediumTest;
40 import androidx.test.runner.AndroidJUnit4;
41 
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 
45 /**
46  * Test {@link MetaKeyKeyListener}.
47  */
48 @MediumTest
49 @RunWith(AndroidJUnit4.class)
50 public class MetaKeyKeyListenerTest extends KeyListenerTestCase {
51     @Test
testPressKey()52     public void testPressKey() {
53         final CharSequence str = "123456";
54         final MetaKeyKeyListener numberKeyListener = new DateKeyListener();
55         final View view = new ImageView(mInstrumentation.getTargetContext());
56         final Editable content = Editable.Factory.getInstance().newEditable(str);
57 
58         content.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
59         content.setSpan(Selection.SELECTION_END, 0, 0, Spanned.SPAN_POINT_POINT);
60         numberKeyListener.onKeyDown(view, content, KeyEvent.KEYCODE_0,
61                 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0));
62         assertEquals('0', content.charAt(0));
63 
64         content.setSpan(Selection.SELECTION_START, 1, 1, Spanned.SPAN_POINT_POINT);
65         content.setSpan(Selection.SELECTION_END, 1, 1, Spanned.SPAN_POINT_POINT);
66         numberKeyListener.onKeyDown(view, content, KeyEvent.KEYCODE_2,
67                 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_2));
68         assertEquals('2', content.charAt(1));
69 
70         content.setSpan(Selection.SELECTION_START, 3, 3, Spanned.SPAN_POINT_POINT);
71         content.setSpan(Selection.SELECTION_END, 3, 3, Spanned.SPAN_POINT_POINT);
72         numberKeyListener.onKeyDown(view, content, KeyEvent.KEYCODE_3,
73                 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_3));
74         assertEquals('3', content.charAt(3));
75     }
76 
77     @Test
testReleaseKey()78     public void testReleaseKey() {
79         final CharSequence str = "123456";
80         final MetaKeyKeyListener numberKeyListener = new DateKeyListener();
81         final View view = new ImageView(mInstrumentation.getTargetContext());
82         final Editable content = Editable.Factory.getInstance().newEditable(str);
83 
84         content.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
85         content.setSpan(Selection.SELECTION_END, 0, 0, Spanned.SPAN_POINT_POINT);
86         numberKeyListener.onKeyUp(view, content, KeyEvent.KEYCODE_0,
87                 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0));
88         assertEquals(str.charAt(0), content.charAt(0));
89 
90         content.setSpan(Selection.SELECTION_START, 1, 1, Spanned.SPAN_POINT_POINT);
91         content.setSpan(Selection.SELECTION_END, 1, 1, Spanned.SPAN_POINT_POINT);
92         numberKeyListener.onKeyUp(view, content, KeyEvent.KEYCODE_2,
93                 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_2));
94         assertEquals(str.charAt(1), content.charAt(1));
95 
96         content.setSpan(Selection.SELECTION_START, 3, 3, Spanned.SPAN_POINT_POINT);
97         content.setSpan(Selection.SELECTION_END, 3, 3, Spanned.SPAN_POINT_POINT);
98         numberKeyListener.onKeyUp(view, content, KeyEvent.KEYCODE_3,
99                 new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_3));
100         assertEquals(str.charAt(3), content.charAt(3));
101     }
102 
103     @Test
testAdjustMetaAfterKeypress()104     public void testAdjustMetaAfterKeypress() {
105         CharSequence str = "123456";
106         Spannable content = Editable.Factory.getInstance().newEditable(str);
107         content.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
108         int len = str.length(); // for one line less than 100
109         content.setSpan( Selection.SELECTION_END, len, len, Spanned.SPAN_POINT_POINT);
110         MetaKeyKeyListener.adjustMetaAfterKeypress(content);
111         assertEquals(Spanned.SPAN_POINT_POINT, content.getSpanFlags(Selection.SELECTION_START));
112         assertEquals(Spanned.SPAN_POINT_POINT, content.getSpanFlags(Selection.SELECTION_END));
113 
114         str = "abc";
115         content = Editable.Factory.getInstance().newEditable(str);
116         content.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
117         len = str.length(); // for one line less than 100
118         content.setSpan( Selection.SELECTION_END, len, len, Spanned.SPAN_POINT_POINT);
119         MetaKeyKeyListener.adjustMetaAfterKeypress(content);
120         assertEquals(Spanned.SPAN_POINT_POINT, content.getSpanFlags(Selection.SELECTION_START));
121         assertEquals(Spanned.SPAN_POINT_POINT, content.getSpanFlags(Selection.SELECTION_END));
122 
123         str = "#@%#$^%^";
124         content = Editable.Factory.getInstance().newEditable(str);
125         content.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
126         len = str.length(); // for one line less than 100
127         content.setSpan( Selection.SELECTION_END, len, len, Spanned.SPAN_POINT_POINT);
128         MetaKeyKeyListener.adjustMetaAfterKeypress(content);
129         assertEquals(Spanned.SPAN_POINT_POINT, content.getSpanFlags(Selection.SELECTION_START));
130         assertEquals(Spanned.SPAN_POINT_POINT, content.getSpanFlags(Selection.SELECTION_END));
131     }
132 
133     @Test
testAdjustMetaAfterKeypress2()134     public void testAdjustMetaAfterKeypress2() {
135         long state = MetaKeyKeyListener.adjustMetaAfterKeypress(MetaKeyKeyListener.META_SHIFT_ON);
136         assertEquals(MetaKeyKeyListener.META_SHIFT_ON, state);
137 
138         state = MetaKeyKeyListener.adjustMetaAfterKeypress(MetaKeyKeyListener.META_ALT_ON);
139         assertEquals(MetaKeyKeyListener.META_ALT_ON, state);
140 
141         state = MetaKeyKeyListener.adjustMetaAfterKeypress(MetaKeyKeyListener.META_SYM_ON);
142         assertEquals(MetaKeyKeyListener.META_SYM_ON, state);
143 
144         state = MetaKeyKeyListener.adjustMetaAfterKeypress(0);
145         assertEquals(0, state);
146     }
147 
148     @Test
testResetMetaState()149     public void testResetMetaState() {
150         CharSequence str = "123456";
151         Spannable text = Editable.Factory.getInstance().newEditable(str);
152         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
153         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
154         MetaKeyKeyListener.resetMetaState(text);
155         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
156         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
157 
158         str = "abc";
159         text = Editable.Factory.getInstance().newEditable(str);
160         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
161         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
162         MetaKeyKeyListener.resetMetaState(text);
163         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
164         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
165 
166         str = "#@%#$^%^";
167         text = Editable.Factory.getInstance().newEditable(str);
168         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
169         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
170         MetaKeyKeyListener.resetMetaState(text);
171         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
172         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
173     }
174 
175     @Test
testGetMetaState()176     public void testGetMetaState() {
177         assertEquals(0, MetaKeyKeyListener.getMetaState("123456"));
178         assertEquals(0, MetaKeyKeyListener.getMetaState("abc"));
179         assertEquals(0, MetaKeyKeyListener.getMetaState("@#$$#^$^"));
180 
181         assertEquals(0,
182                      MetaKeyKeyListener.getMetaState("123456"),
183                      MetaKeyKeyListener.META_SHIFT_ON);
184         assertEquals(0,
185                      MetaKeyKeyListener.getMetaState("abc"),
186                      MetaKeyKeyListener.META_ALT_ON);
187         assertEquals(0,
188                      MetaKeyKeyListener.getMetaState("@#$$#^$^"),
189                      MetaKeyKeyListener.META_SYM_ON);
190 
191         assertEquals(0, MetaKeyKeyListener.getMetaState("123456", 0));
192         assertEquals(0, MetaKeyKeyListener.getMetaState("abc", -1));
193         assertEquals(0, MetaKeyKeyListener.getMetaState("@#$$#^$^", Integer.MAX_VALUE));
194 
195         assertEquals(0,
196                 MetaKeyKeyListener.getMetaState("123456", MetaKeyKeyListener.META_SHIFT_ON));
197         assertEquals(0, MetaKeyKeyListener.getMetaState("abc", MetaKeyKeyListener.META_ALT_ON));
198         assertEquals(0,
199                 MetaKeyKeyListener.getMetaState("@#$$#^$^", MetaKeyKeyListener.META_SYM_ON));
200     }
201 
202     @Test
testGetMetaState2()203     public void testGetMetaState2() {
204         assertEquals(0, MetaKeyKeyListener.getMetaState(0));
205         assertEquals(MetaKeyKeyListener.META_SHIFT_ON,
206                 MetaKeyKeyListener.getMetaState(MetaKeyKeyListener.META_SHIFT_ON));
207         assertEquals(MetaKeyKeyListener.META_CAP_LOCKED,
208                 MetaKeyKeyListener.getMetaState(MetaKeyKeyListener.META_CAP_LOCKED));
209 
210         assertEquals(0, MetaKeyKeyListener.getMetaState(0, MetaKeyKeyListener.META_SYM_ON));
211         assertEquals(1, MetaKeyKeyListener.getMetaState(MetaKeyKeyListener.META_SYM_ON,
212                 MetaKeyKeyListener.META_SYM_ON));
213         assertEquals(2, MetaKeyKeyListener.getMetaState(MetaKeyKeyListener.META_SYM_LOCKED,
214                 MetaKeyKeyListener.META_SYM_ON));
215     }
216 
217     @Test
testGetMetaState_withCharSequenceAndKeyEvent()218     public void testGetMetaState_withCharSequenceAndKeyEvent() {
219         KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0, 0,
220                 KeyEvent.META_SHIFT_MASK);
221 
222         assertEquals(KeyEvent.META_SHIFT_MASK, MetaKeyKeyListener.getMetaState(null, event));
223         assertEquals(KeyEvent.META_SHIFT_MASK, MetaKeyKeyListener.getMetaState("", event));
224     }
225 
226     @Test
testGetMetaState_withCharSequenceAndMetaAndKeyEvent()227     public void testGetMetaState_withCharSequenceAndMetaAndKeyEvent() {
228         KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0, 0,
229                 KeyEvent.META_CTRL_ON);
230 
231         assertEquals(0, MetaKeyKeyListener.getMetaState("", MetaKeyKeyListener.META_SHIFT_ON,
232                 event));
233 
234         event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0, 0,
235                 KeyEvent.META_SHIFT_ON);
236 
237         assertEquals(1, MetaKeyKeyListener.getMetaState("", MetaKeyKeyListener.META_SHIFT_ON,
238                 event));
239 
240         event = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_0, 0,
241                 MetaKeyKeyListener.META_SYM_LOCKED);
242 
243         assertEquals(2, MetaKeyKeyListener.getMetaState("", MetaKeyKeyListener.META_SYM_ON,
244                 event));
245 
246         assertEquals(2, MetaKeyKeyListener.getMetaState(null, MetaKeyKeyListener.META_SYM_ON,
247                 event));
248     }
249 
250     @Test
testIsMetaTracker()251     public void testIsMetaTracker() {
252         assertFalse(MetaKeyKeyListener.isMetaTracker("123456", new Object()));
253         assertFalse(MetaKeyKeyListener.isMetaTracker("abc", new Object()));
254         assertFalse(MetaKeyKeyListener.isMetaTracker("@#$$#^$^", new Object()));
255     }
256 
257     @Test
testIsSelectingMetaTracker()258     public void testIsSelectingMetaTracker() {
259         assertFalse(MetaKeyKeyListener.isSelectingMetaTracker("123456", new Object()));
260         assertFalse(MetaKeyKeyListener.isSelectingMetaTracker("abc", new Object()));
261         assertFalse(MetaKeyKeyListener.isSelectingMetaTracker("@#$$#^$^", new Object()));
262     }
263 
264     @Test
testResetLockedMeta()265     public void testResetLockedMeta() {
266         MockMetaKeyKeyListener mockMetaKeyKeyListener = new MockMetaKeyKeyListener();
267 
268         MockSpannable str = spy(new MockSpannable());
269         str.setSpan(new Object(), 0, 0, Spannable.SPAN_MARK_MARK
270                 | (4 << Spannable.SPAN_USER_SHIFT));
271         verify(str, never()).removeSpan(any());
272         mockMetaKeyKeyListener.callResetLockedMeta(str);
273         verify(str, atLeastOnce()).removeSpan(any());
274 
275         str = spy(new MockSpannable());
276         str.setSpan(new Object(), 0, 0, Spannable.SPAN_MARK_POINT);
277         verify(str, never()).removeSpan(any());
278         mockMetaKeyKeyListener.callResetLockedMeta(str);
279         verify(str, never()).removeSpan(any());
280 
281         try {
282             mockMetaKeyKeyListener.callResetLockedMeta(null);
283             fail("should throw NullPointerException.");
284         } catch (NullPointerException e) {
285         }
286     }
287 
288     @Test
testResetLockedMeta2()289     public void testResetLockedMeta2() {
290         long state = MetaKeyKeyListener.resetLockedMeta(MetaKeyKeyListener.META_CAP_LOCKED);
291         assertEquals(0, state);
292 
293         state = MetaKeyKeyListener.resetLockedMeta(MetaKeyKeyListener.META_SHIFT_ON);
294         assertEquals(MetaKeyKeyListener.META_SHIFT_ON, state);
295 
296         state = MetaKeyKeyListener.resetLockedMeta(MetaKeyKeyListener.META_ALT_LOCKED);
297         assertEquals(0, state);
298 
299         state = MetaKeyKeyListener.resetLockedMeta(MetaKeyKeyListener.META_ALT_ON);
300         assertEquals(MetaKeyKeyListener.META_ALT_ON, state);
301 
302         state = MetaKeyKeyListener.resetLockedMeta(MetaKeyKeyListener.META_SYM_LOCKED);
303         assertEquals(0, state);
304 
305         state = MetaKeyKeyListener.resetLockedMeta(MetaKeyKeyListener.META_SYM_ON);
306         assertEquals(MetaKeyKeyListener.META_SYM_ON, state);
307     }
308 
309     @Test
testClearMetaKeyState()310     public void testClearMetaKeyState() {
311         final MetaKeyKeyListener numberKeyListener = new DateKeyListener();
312         CharSequence str = "123456";
313         Editable text = Editable.Factory.getInstance().newEditable(str);
314         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
315         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
316         numberKeyListener.clearMetaKeyState(null, text, MetaKeyKeyListener.META_SHIFT_ON);
317         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
318         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
319 
320         str = "abc";
321         text = Editable.Factory.getInstance().newEditable(str);
322         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
323         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
324         numberKeyListener.clearMetaKeyState(null, text, MetaKeyKeyListener.META_ALT_ON);
325         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
326         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
327 
328         str = "#@%#$^%^";
329         text = Editable.Factory.getInstance().newEditable(str);
330         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
331         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
332         numberKeyListener.clearMetaKeyState(null, text, MetaKeyKeyListener.META_SYM_ON);
333         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
334         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
335     }
336 
337     @Test
testClearMetaKeyState2()338     public void testClearMetaKeyState2() {
339         CharSequence str = "123456";
340         Editable text = Editable.Factory.getInstance().newEditable(str);
341         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
342         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
343         MetaKeyKeyListener.clearMetaKeyState(text, MetaKeyKeyListener.META_SHIFT_ON);
344         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
345         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
346 
347         str = "abc";
348         text = Editable.Factory.getInstance().newEditable(str);
349         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
350         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
351         MetaKeyKeyListener.clearMetaKeyState(text, MetaKeyKeyListener.META_ALT_ON);
352         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
353         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
354 
355         str = "#@%#$^%^";
356         text = Editable.Factory.getInstance().newEditable(str);
357         text.setSpan(Selection.SELECTION_START, 0, 0, Spanned.SPAN_POINT_POINT);
358         text.setSpan(Selection.SELECTION_END, str.length(), str.length(), Spanned.SPAN_POINT_POINT);
359         MetaKeyKeyListener.clearMetaKeyState(text, MetaKeyKeyListener.META_SYM_ON);
360         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_START));
361         assertEquals(Spanned.SPAN_POINT_POINT, text.getSpanFlags(Selection.SELECTION_END));
362     }
363 
364     @Test
testClearMetaKeyState3()365     public void testClearMetaKeyState3() {
366         final MetaKeyKeyListener metaKeyKeyListener = new MetaKeyKeyListener() {};
367         long state = metaKeyKeyListener.clearMetaKeyState(MetaKeyKeyListener.META_CAP_LOCKED,
368                 MetaKeyKeyListener.META_SHIFT_ON);
369         assertEquals(0, state);
370 
371         state = metaKeyKeyListener.clearMetaKeyState(MetaKeyKeyListener.META_SHIFT_ON,
372                 MetaKeyKeyListener.META_SHIFT_ON);
373         assertEquals(MetaKeyKeyListener.META_SHIFT_ON, state);
374 
375         state = metaKeyKeyListener.clearMetaKeyState(MetaKeyKeyListener.META_ALT_LOCKED,
376                 MetaKeyKeyListener.META_ALT_ON);
377         assertEquals(0, state);
378 
379         state = metaKeyKeyListener.clearMetaKeyState(MetaKeyKeyListener.META_ALT_ON,
380                 MetaKeyKeyListener.META_ALT_ON);
381         assertEquals(MetaKeyKeyListener.META_ALT_ON, state);
382 
383         state = metaKeyKeyListener.clearMetaKeyState(MetaKeyKeyListener.META_SYM_LOCKED,
384                 MetaKeyKeyListener.META_SYM_ON);
385         assertEquals(0, state);
386 
387         state = metaKeyKeyListener.clearMetaKeyState(MetaKeyKeyListener.META_SYM_ON,
388                 MetaKeyKeyListener.META_SYM_ON);
389         assertEquals(MetaKeyKeyListener.META_SYM_ON, state);
390     }
391 
392     @Test
testHandleKeyDown()393     public void testHandleKeyDown() {
394         KeyEvent fullEvent = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT,
395                 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0);
396         long state = MetaKeyKeyListener.handleKeyDown(MetaKeyKeyListener.META_CAP_LOCKED,
397                 KeyEvent.KEYCODE_SHIFT_LEFT, fullEvent);
398         assertEquals(0, state);
399     }
400 
401     @Test
testHandleKeyUp()402     public void testHandleKeyUp() {
403         KeyEvent fullEvent = new KeyEvent(0, 0, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SHIFT_LEFT,
404                 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0);
405         long state = MetaKeyKeyListener.handleKeyUp(MetaKeyKeyListener.META_CAP_LOCKED,
406                 KeyEvent.KEYCODE_SHIFT_LEFT, fullEvent);
407         assertEquals(0, state);
408     }
409 
410     /**
411      * A mocked {@link android.text.method.MetaKeyKeyListener} for testing purposes.
412      *
413      * Allows {@link MetaKeyKeyListenerTest} to call
414      * {@link android.text.method.MetaKeyKeyListener.resetLockedMeta(Spannable)}.
415      */
416     private class MockMetaKeyKeyListener extends MetaKeyKeyListener {
callResetLockedMeta(Spannable content)417         public void callResetLockedMeta(Spannable content) {
418             MetaKeyKeyListener.resetLockedMeta(content);
419         }
420     }
421 
422     /**
423      * A mocked {@link android.text.Spannable} for testing purposes.
424      */
425     public static class MockSpannable implements Spannable {
426         private int mFlags;
427 
setSpan(Object what, int start, int end, int flags)428         public void setSpan(Object what, int start, int end, int flags) {
429             mFlags = flags;
430         }
431 
removeSpan(Object what)432         public void removeSpan(Object what) {
433         }
434 
getSpans(int start, int end, Class<T> type)435         public <T> T[] getSpans(int start, int end, Class<T> type) {
436             return null;
437         }
438 
getSpanStart(Object tag)439         public int getSpanStart(Object tag) {
440             return 0;
441         }
442 
getSpanEnd(Object tag)443         public int getSpanEnd(Object tag) {
444             return 0;
445         }
446 
getSpanFlags(Object tag)447         public int getSpanFlags(Object tag) {
448             return mFlags;
449         }
450 
451         @SuppressWarnings("unchecked")
nextSpanTransition(int start, int limit, Class type)452         public int nextSpanTransition(int start, int limit, Class type) {
453             return 0;
454         }
455 
charAt(int index)456         public char charAt(int index) {
457             return 0;
458         }
459 
length()460         public int length() {
461             return 0;
462         }
463 
subSequence(int start, int end)464         public CharSequence subSequence(int start, int end) {
465             return null;
466         }
467     }
468 }
469