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