1 /*
2  * Copyright (C) 2018 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 com.android.server.wm;
18 
19 import static android.os.Process.FIRST_APPLICATION_UID;
20 import static android.os.Process.NFC_UID;
21 import static android.os.Process.SYSTEM_UID;
22 import static android.os.UserHandle.USER_ALL;
23 import static android.os.UserHandle.USER_SYSTEM;
24 
25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
26 
27 import static org.hamcrest.Matchers.containsString;
28 import static org.junit.Assert.assertFalse;
29 import static org.junit.Assert.assertThat;
30 import static org.junit.Assert.assertTrue;
31 import static org.junit.Assert.fail;
32 
33 import android.os.Binder;
34 import android.os.Handler;
35 import android.os.IBinder;
36 import android.os.UserHandle;
37 import android.platform.test.annotations.Presubmit;
38 import android.util.SparseBooleanArray;
39 
40 import com.android.server.wm.LockTaskController.LockTaskToken;
41 
42 import org.junit.Before;
43 import org.junit.Test;
44 
45 import java.lang.reflect.Constructor;
46 
47 @Presubmit
48 public class KeyguardDisableHandlerTest {
49 
50     private KeyguardDisableHandler mKeyguardDisable;
51 
52     private boolean mKeyguardEnabled;
53     private SparseBooleanArray mKeyguardSecure = new SparseBooleanArray();
54     private SparseBooleanArray mDpmRequiresPassword = new SparseBooleanArray();
55 
56     @Before
setUp()57     public void setUp() throws Exception {
58         mKeyguardEnabled = true;
59 
60         mKeyguardDisable = new KeyguardDisableHandler(new KeyguardDisableHandler.Injector() {
61             @Override
62             public boolean dpmRequiresPassword(int userId) {
63                 return mDpmRequiresPassword.get(userId);
64             }
65 
66             @Override
67             public boolean isKeyguardSecure(int userId) {
68                 return mKeyguardSecure.get(userId);
69             }
70 
71             @Override
72             public int getProfileParentId(int userId) {
73                 return userId;
74             }
75 
76             @Override
77             public void enableKeyguard(boolean enabled) {
78                 mKeyguardEnabled = enabled;
79             }
80         }, mock(Handler.class)) {
81             @Override
82             public void disableKeyguard(IBinder token, String tag, int callingUid, int userId) {
83                 super.disableKeyguard(token, tag, callingUid, userId);
84                 // In the actual code, the update is posted to the handler thread. Eagerly update
85                 // here to simplify the test.
86                 updateKeyguardEnabled(userId);
87             }
88 
89             @Override
90             public void reenableKeyguard(IBinder token, int callingUid, int userId) {
91                 super.reenableKeyguard(token, callingUid, userId);
92                 // In the actual code, the update is posted to the handler thread. Eagerly update
93                 // here to simplify the test.
94                 updateKeyguardEnabled(userId);
95             }
96         };
97     }
98 
99     @Test
starts_enabled()100     public void starts_enabled() {
101         assertTrue(mKeyguardEnabled);
102         mKeyguardDisable.updateKeyguardEnabled(USER_ALL);
103         assertTrue(mKeyguardEnabled);
104     }
105 
106     @Test
disable_fromApp_disables()107     public void disable_fromApp_disables() {
108         mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
109         assertFalse(mKeyguardEnabled);
110     }
111 
112     @Test
disable_fromApp_secondaryUser_disables()113     public void disable_fromApp_secondaryUser_disables() {
114         mKeyguardDisable.setCurrentUser(1);
115         mKeyguardDisable.disableKeyguard(new Binder(), "Tag",
116                 UserHandle.getUid(1, FIRST_APPLICATION_UID), 1);
117         assertFalse(mKeyguardEnabled);
118     }
119 
120     @Test
disable_fromSystem_LockTask_disables()121     public void disable_fromSystem_LockTask_disables() {
122         mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
123         assertFalse(mKeyguardEnabled);
124     }
125 
126     @Test
disable_fromSystem_genericToken_fails()127     public void disable_fromSystem_genericToken_fails() {
128         try {
129             mKeyguardDisable.disableKeyguard(new Binder(), "Tag", SYSTEM_UID, USER_SYSTEM);
130             fail("Expected exception not thrown");
131         } catch (UnsupportedOperationException e) {
132             assertThat(e.getMessage(), containsString("Only apps can use the KeyguardLock API"));
133         }
134         assertTrue(mKeyguardEnabled);
135     }
136 
137     @Test
disable_fromNonApp_genericToken_fails()138     public void disable_fromNonApp_genericToken_fails() {
139         try {
140             mKeyguardDisable.disableKeyguard(new Binder(), "Tag", NFC_UID, USER_SYSTEM);
141             fail("Expected exception not thrown");
142         } catch (UnsupportedOperationException e) {
143             assertThat(e.getMessage(), containsString("Only apps can use the KeyguardLock API"));
144         }
145         assertTrue(mKeyguardEnabled);
146     }
147 
148     @Test
disable_fromApp_secure_staysEnabled()149     public void disable_fromApp_secure_staysEnabled() {
150         configureIsSecure(true, USER_SYSTEM);
151         mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
152         assertTrue(mKeyguardEnabled);
153     }
154 
155     @Test
disable_fromApp_dpmRequiresPassword_staysEnabled()156     public void disable_fromApp_dpmRequiresPassword_staysEnabled() {
157         configureDpmRequiresPassword(true, USER_SYSTEM);
158         mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
159         assertTrue(mKeyguardEnabled);
160     }
161 
162     @Test
disable_fromSystem_LockTask_secure_disables()163     public void disable_fromSystem_LockTask_secure_disables() {
164         configureIsSecure(true, USER_SYSTEM);
165         mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
166         assertFalse(mKeyguardEnabled);
167     }
168 
169     @Test
disable_fromSystem_LockTask_requiresDpm_staysEnabled()170     public void disable_fromSystem_LockTask_requiresDpm_staysEnabled() {
171         configureDpmRequiresPassword(true, USER_SYSTEM);
172         mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
173         assertTrue(mKeyguardEnabled);
174     }
175 
176     @Test
disable_fromApp_thenSecure_reenables()177     public void disable_fromApp_thenSecure_reenables() {
178         mKeyguardDisable.disableKeyguard(new Binder(), "Tag", FIRST_APPLICATION_UID, USER_SYSTEM);
179         configureIsSecure(true, USER_SYSTEM);
180         assertTrue(mKeyguardEnabled);
181     }
182 
183     @Test
disable_fromSystem_LockTask_thenRequiresDpm_reenables()184     public void disable_fromSystem_LockTask_thenRequiresDpm_reenables() {
185         mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
186         configureDpmRequiresPassword(true, USER_SYSTEM);
187         assertTrue(mKeyguardEnabled);
188     }
189 
190     @Test
user_switch_to_enabledUser_applies_enabled()191     public void user_switch_to_enabledUser_applies_enabled() {
192         mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag", SYSTEM_UID, USER_SYSTEM);
193         assertFalse("test setup failed", mKeyguardEnabled);
194         mKeyguardDisable.setCurrentUser(1);
195         assertTrue(mKeyguardEnabled);
196     }
197 
198     @Test
user_switch_to_disabledUser_applies_disabled()199     public void user_switch_to_disabledUser_applies_disabled() {
200         mKeyguardDisable.disableKeyguard(createLockTaskToken(), "Tag",
201                 SYSTEM_UID, 1);
202         assertTrue("test setup failed", mKeyguardEnabled);
203         mKeyguardDisable.setCurrentUser(1);
204         assertFalse(mKeyguardEnabled);
205     }
206 
configureIsSecure(boolean secure, int userId)207     private void configureIsSecure(boolean secure, int userId) {
208         mKeyguardSecure.put(userId, secure);
209         mKeyguardDisable.updateKeyguardEnabled(userId);
210     }
211 
configureDpmRequiresPassword(boolean requiresPassword, int userId)212     private void configureDpmRequiresPassword(boolean requiresPassword, int userId) {
213         mDpmRequiresPassword.put(userId, requiresPassword);
214         mKeyguardDisable.updateKeyguardEnabled(userId);
215     }
216 
createLockTaskToken()217     private LockTaskToken createLockTaskToken() {
218         try {
219             final Constructor<LockTaskToken> constructor =
220                     LockTaskToken.class.getDeclaredConstructor();
221             constructor.setAccessible(true);
222             return constructor.newInstance();
223         } catch (Exception e) {
224             throw new RuntimeException(e);
225         }
226     }
227 }
228