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