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
17package com.android.internal.policy.impl;
18
19import android.content.Context;
20import com.android.internal.policy.impl.KeyguardViewCallback;
21import com.android.internal.telephony.IccCard;
22import android.content.res.Configuration;
23import android.test.AndroidTestCase;
24import android.view.View;
25import android.view.KeyEvent;
26import com.android.internal.widget.LockPatternUtils;
27import com.google.android.collect.Lists;
28
29import java.util.List;
30
31/**
32 * Tests for {@link com.android.internal.policy.impl.LockPatternKeyguardView},
33 * which handles the management of screens while the keyguard is showing.
34 */
35public class LockPatternKeyguardViewTest extends AndroidTestCase {
36    private MockUpdateMonitor mUpdateMonitor;
37    private LockPatternUtils mLockPatternUtils;
38    private TestableLockPatternKeyguardView mLPKV;
39    private MockKeyguardCallback mKeyguardViewCallback;
40
41    private static class MockUpdateMonitor extends KeyguardUpdateMonitor {
42
43        public IccCard.State simState = IccCard.State.READY;
44
45        private MockUpdateMonitor(Context context) {
46            super(context);
47        }
48
49        @Override
50        public IccCard.State getSimState() {
51            return simState;
52        }
53    }
54
55    private static class MockLockPatternUtils extends LockPatternUtils {
56        boolean isLockPatternEnabled = true;
57        public boolean isPermanentlyLocked = false;
58
59        public MockLockPatternUtils(Context context) {
60            super(context);
61        }
62
63        @Override
64        public boolean isLockPatternEnabled() {
65            return isLockPatternEnabled;
66        }
67
68        @Override
69        public void setLockPatternEnabled(boolean lockPatternEnabled) {
70            isLockPatternEnabled = lockPatternEnabled;
71        }
72
73        @Override
74        public boolean isPermanentlyLocked() {
75            return isPermanentlyLocked;
76        }
77
78        public void setPermanentlyLocked(boolean permanentlyLocked) {
79            isPermanentlyLocked = permanentlyLocked;
80        }
81    }
82
83    private static class MockKeyguardScreen extends View implements KeyguardScreen {
84
85        private int mOnPauseCount = 0;
86        private int mOnResumeCount = 0;
87        private int mCleanupCount = 0;
88
89        private MockKeyguardScreen(Context context) {
90            super(context);
91            setFocusable(true);
92        }
93
94        /** {@inheritDoc} */
95        public boolean needsInput() {
96            return false;
97        }
98
99        /** {@inheritDoc} */
100        public void onPause() {
101            mOnPauseCount++;
102        }
103
104        /** {@inheritDoc} */
105        public void onResume() {
106            mOnResumeCount++;
107        }
108
109        /** {@inheritDoc} */
110        public void cleanUp() {
111            mCleanupCount++;
112        }
113
114        public int getOnPauseCount() {
115            return mOnPauseCount;
116        }
117
118        public int getOnResumeCount() {
119            return mOnResumeCount;
120        }
121
122        public int getCleanupCount() {
123            return mCleanupCount;
124        }
125    }
126
127    /**
128     * Allows us to inject the lock and unlock views to simulate their behavior
129     * and detect their creation.
130     */
131    private static class TestableLockPatternKeyguardView extends LockPatternKeyguardView {
132        private List<MockKeyguardScreen> mInjectedLockScreens;
133        private List<MockKeyguardScreen> mInjectedUnlockScreens;
134
135
136
137        private TestableLockPatternKeyguardView(Context context, KeyguardViewCallback callback,
138                KeyguardUpdateMonitor updateMonitor,
139                LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
140            super(context, callback, updateMonitor, lockPatternUtils, controller);
141        }
142
143        @Override
144        View createLockScreen() {
145            final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
146            if (mInjectedLockScreens == null) mInjectedLockScreens = Lists.newArrayList();
147            mInjectedLockScreens.add(newView);
148            return newView;
149        }
150
151        @Override
152        View createUnlockScreenFor(UnlockMode unlockMode) {
153            final MockKeyguardScreen newView = new MockKeyguardScreen(getContext());
154            if (mInjectedUnlockScreens == null) mInjectedUnlockScreens = Lists.newArrayList();
155            mInjectedUnlockScreens.add(newView);
156            return newView;
157        }
158
159        public List<MockKeyguardScreen> getInjectedLockScreens() {
160            return mInjectedLockScreens;
161        }
162
163        public List<MockKeyguardScreen> getInjectedUnlockScreens() {
164            return mInjectedUnlockScreens;
165        }
166    }
167
168    private static class MockKeyguardCallback implements KeyguardViewCallback {
169
170        private int mPokeWakelockCount = 0;
171        private int mKeyguardDoneCount = 0;
172
173        public void pokeWakelock() {
174            mPokeWakelockCount++;
175        }
176
177        public void pokeWakelock(int millis) {
178            mPokeWakelockCount++;
179        }
180
181        public void keyguardDone(boolean authenticated) {
182            mKeyguardDoneCount++;
183        }
184
185        public void keyguardDoneDrawing() {
186
187        }
188
189        public int getPokeWakelockCount() {
190            return mPokeWakelockCount;
191        }
192
193        public int getKeyguardDoneCount() {
194            return mKeyguardDoneCount;
195        }
196    }
197
198    @Override
199    protected void setUp() throws Exception {
200        super.setUp();
201        mUpdateMonitor = new MockUpdateMonitor(getContext());
202        mLockPatternUtils = new MockLockPatternUtils(getContext());
203        mKeyguardViewCallback = new MockKeyguardCallback();
204
205        mLPKV = new TestableLockPatternKeyguardView(getContext(), mKeyguardViewCallback,
206                mUpdateMonitor, mLockPatternUtils, new KeyguardWindowController() {
207            public void setNeedsInput(boolean needsInput) {
208            }
209        });
210    }
211
212    public void testStateAfterCreatedWhileScreenOff() {
213
214        assertEquals(1, mLPKV.getInjectedLockScreens().size());
215        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
216
217        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
218        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
219
220        assertEquals(0, lockScreen.getOnPauseCount());
221        assertEquals(0, lockScreen.getOnResumeCount());
222        assertEquals(0, lockScreen.getCleanupCount());
223
224        assertEquals(0, unlockScreen.getOnPauseCount());
225        assertEquals(0, unlockScreen.getOnResumeCount());
226        assertEquals(0, unlockScreen.getCleanupCount());
227
228        assertEquals(0, mKeyguardViewCallback.getPokeWakelockCount());
229        assertEquals(0, mKeyguardViewCallback.getKeyguardDoneCount());
230    }
231
232    public void testWokenByNonMenuKey() {
233        mLPKV.wakeWhenReadyTq(0);
234
235        // should have poked the wakelock to turn on the screen
236        assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
237
238        // shouldn't be any additional views created
239        assertEquals(1, mLPKV.getInjectedLockScreens().size());
240        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
241        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
242        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
243
244        // lock screen should be only visible one
245        assertEquals(View.VISIBLE, lockScreen.getVisibility());
246        assertEquals(View.GONE, unlockScreen.getVisibility());
247
248        // on resume not called until screen turns on
249        assertEquals(0, lockScreen.getOnPauseCount());
250        assertEquals(0, lockScreen.getOnResumeCount());
251        assertEquals(0, lockScreen.getCleanupCount());
252
253        assertEquals(0, unlockScreen.getOnPauseCount());
254        assertEquals(0, unlockScreen.getOnResumeCount());
255        assertEquals(0, unlockScreen.getCleanupCount());
256
257        // simulate screen turning on
258        mLPKV.onScreenTurnedOn();
259
260        assertEquals(0, lockScreen.getOnPauseCount());
261        assertEquals(1, lockScreen.getOnResumeCount());
262        assertEquals(0, lockScreen.getCleanupCount());
263
264        assertEquals(0, unlockScreen.getOnPauseCount());
265        assertEquals(0, unlockScreen.getOnResumeCount());
266        assertEquals(0, unlockScreen.getCleanupCount());
267    }
268
269    public void testWokenByMenuKeyWhenPatternSet() {
270        assertEquals(true, mLockPatternUtils.isLockPatternEnabled());
271
272        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
273
274        // should have poked the wakelock to turn on the screen
275        assertEquals(1, mKeyguardViewCallback.getPokeWakelockCount());
276
277        // shouldn't be any additional views created
278        assertEquals(1, mLPKV.getInjectedLockScreens().size());
279        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
280        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
281        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
282
283        // unlock screen should be only visible one
284        assertEquals(View.GONE, lockScreen.getVisibility());
285        assertEquals(View.VISIBLE, unlockScreen.getVisibility());
286    }
287
288    public void testScreenRequestsRecreation() {
289        mLPKV.wakeWhenReadyTq(0);
290        mLPKV.onScreenTurnedOn();
291
292        assertEquals(1, mLPKV.getInjectedLockScreens().size());
293        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
294        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
295
296        assertEquals(0, lockScreen.getOnPauseCount());
297        assertEquals(1, lockScreen.getOnResumeCount());
298
299        // simulate screen asking to be recreated
300        mLPKV.mKeyguardScreenCallback.recreateMe(new Configuration());
301
302        // should have been recreated
303        assertEquals(2, mLPKV.getInjectedLockScreens().size());
304        assertEquals(2, mLPKV.getInjectedUnlockScreens().size());
305
306        // both old screens should have been cleaned up
307        assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getCleanupCount());
308        assertEquals(1, mLPKV.getInjectedUnlockScreens().get(0).getCleanupCount());
309
310        // old lock screen should have been paused
311        assertEquals(1, mLPKV.getInjectedLockScreens().get(0).getOnPauseCount());
312        assertEquals(0, mLPKV.getInjectedUnlockScreens().get(0).getOnPauseCount());
313
314        // new lock screen should have been resumed
315        assertEquals(1, mLPKV.getInjectedLockScreens().get(1).getOnResumeCount());
316        assertEquals(0, mLPKV.getInjectedUnlockScreens().get(1).getOnResumeCount());
317    }
318
319    public void testMenuDoesntGoToUnlockScreenOnWakeWhenPukLocked() {
320        // PUK locked
321        mUpdateMonitor.simState = IccCard.State.PUK_REQUIRED;
322
323        // wake by menu
324        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
325
326        assertEquals(1, mLPKV.getInjectedLockScreens().size());
327        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
328        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
329        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
330
331        // lock screen should be only visible one
332        assertEquals(View.VISIBLE, lockScreen.getVisibility());
333        assertEquals(View.GONE, unlockScreen.getVisibility());
334    }
335
336    public void testMenuGoesToLockScreenWhenDeviceNotSecure() {
337        mLockPatternUtils.setLockPatternEnabled(false);
338
339        // wake by menu
340        mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);
341
342        assertEquals(1, mLPKV.getInjectedLockScreens().size());
343        assertEquals(1, mLPKV.getInjectedUnlockScreens().size());
344        MockKeyguardScreen lockScreen = mLPKV.getInjectedLockScreens().get(0);
345        MockKeyguardScreen unlockScreen = mLPKV.getInjectedUnlockScreens().get(0);
346
347        // lock screen should be only visible one
348        assertEquals(View.VISIBLE, lockScreen.getVisibility());
349        assertEquals(View.GONE, unlockScreen.getVisibility());
350    }
351}
352