• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.keyguard;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.AdditionalAnswers.answerVoid;
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.ArgumentMatchers.anyLong;
24 import static org.mockito.ArgumentMatchers.anyString;
25 import static org.mockito.Mockito.doAnswer;
26 import static org.mockito.Mockito.doThrow;
27 import static org.mockito.Mockito.never;
28 import static org.mockito.Mockito.spy;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31 
32 import android.app.admin.IKeyguardCallback;
33 import android.app.admin.IKeyguardClient;
34 import android.content.ComponentName;
35 import android.content.Intent;
36 import android.hardware.display.DisplayManager;
37 import android.os.Binder;
38 import android.os.Handler;
39 import android.os.RemoteException;
40 import android.testing.AndroidTestingRunner;
41 import android.testing.TestableLooper;
42 import android.testing.TestableLooper.RunWithLooper;
43 import android.testing.ViewUtils;
44 import android.view.Display;
45 import android.view.SurfaceControlViewHost;
46 import android.view.SurfaceView;
47 import android.view.View;
48 
49 import androidx.test.filters.SmallTest;
50 
51 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
52 import com.android.systemui.SysuiTestCase;
53 import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
54 
55 import org.junit.After;
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.junit.runner.RunWith;
59 import org.mockito.ArgumentCaptor;
60 import org.mockito.Mock;
61 import org.mockito.MockitoAnnotations;
62 
63 @RunWithLooper
64 @RunWith(AndroidTestingRunner.class)
65 @SmallTest
66 public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
67 
68     private static final int TARGET_USER_ID = 0;
69 
70     private AdminSecondaryLockScreenController mTestController;
71     private ComponentName mComponentName;
72     private Intent mServiceIntent;
73     private TestableLooper mTestableLooper;
74     private KeyguardSecurityContainer mKeyguardSecurityContainer;
75 
76     @Mock
77     private Handler mHandler;
78     @Mock
79     private IKeyguardClient.Stub mKeyguardClient;
80     @Mock
81     private KeyguardSecurityCallback mKeyguardCallback;
82     @Mock
83     private KeyguardUpdateMonitor mUpdateMonitor;
84     @Mock
85     private SelectedUserInteractor mSelectedUserInteractor;
86 
87     private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
88 
89     @Before
setUp()90     public void setUp() {
91         MockitoAnnotations.initMocks(this);
92         when(mSelectedUserInteractor.getSelectedUserId()).thenReturn(TARGET_USER_ID);
93 
94         mKeyguardSecurityContainer = spy(new KeyguardSecurityContainer(mContext));
95         mKeyguardSecurityContainer.setId(View.generateViewId());
96         ViewUtils.attachView(mKeyguardSecurityContainer);
97 
98         mTestableLooper = TestableLooper.get(this);
99         mComponentName = new ComponentName(mContext, "FakeKeyguardClient.class");
100         mServiceIntent = new Intent().setComponent(mComponentName);
101 
102         mContext.addMockService(mComponentName, mKeyguardClient);
103         // Have Stub.asInterface return the mocked interface.
104         when(mKeyguardClient.queryLocalInterface(anyString())).thenReturn(mKeyguardClient);
105         when(mKeyguardClient.asBinder()).thenReturn(mKeyguardClient);
106 
107         Display display = mContext.getSystemService(DisplayManager.class).getDisplay(
108                 Display.DEFAULT_DISPLAY);
109         mSurfacePackage = (new SurfaceControlViewHost(mContext, display,
110                 new Binder())).getSurfacePackage();
111 
112         mTestController = new AdminSecondaryLockScreenController.Factory(
113                 mContext, mKeyguardSecurityContainer, mUpdateMonitor, mHandler,
114                 mSelectedUserInteractor)
115                 .create(mKeyguardCallback);
116     }
117 
118     @After
tearDown()119     public void tearDown() {
120         ViewUtils.detachView(mKeyguardSecurityContainer);
121     }
122 
123     @Test
testShow()124     public void testShow() throws Exception {
125         doAnswer(invocation -> {
126             IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
127             callback.onRemoteContentReady(mSurfacePackage);
128             return null;
129         }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
130 
131         mTestController.show(mServiceIntent);
132 
133         verifySurfaceReady();
134         assertThat(mContext.isBound(mComponentName)).isTrue();
135     }
136 
137     @Test
testShow_dismissedByCallback()138     public void testShow_dismissedByCallback() throws Exception {
139         doAnswer(answerVoid(Runnable::run)).when(mHandler).post(any(Runnable.class));
140         doAnswer(invocation -> {
141             IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
142             callback.onDismiss();
143             return null;
144         }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
145 
146         mTestController.show(mServiceIntent);
147 
148         verifyViewDismissed(verifySurfaceReady());
149     }
150 
151     @Test
testHide()152     public void testHide() throws Exception {
153         // Show the view first, then hide.
154         doAnswer(invocation -> {
155             IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
156             callback.onRemoteContentReady(mSurfacePackage);
157             return null;
158         }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
159 
160         mTestController.show(mServiceIntent);
161         SurfaceView v = verifySurfaceReady();
162 
163         mTestController.hide();
164         verify(mKeyguardSecurityContainer).removeView(v);
165         assertThat(mContext.isBound(mComponentName)).isFalse();
166     }
167 
168     @Test
testHide_notShown()169     public void testHide_notShown() throws Exception {
170         mTestController.hide();
171         // Nothing should happen if trying to hide when the view isn't attached yet.
172         verify(mKeyguardSecurityContainer, never()).removeView(any(SurfaceView.class));
173     }
174 
175     @Test
testDismissed_onCreateKeyguardSurface_RemoteException()176     public void testDismissed_onCreateKeyguardSurface_RemoteException() throws Exception {
177         doThrow(new RemoteException()).when(mKeyguardClient)
178                 .onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
179 
180         mTestController.show(mServiceIntent);
181 
182         verifyViewDismissed(verifySurfaceReady());
183     }
184 
185     @Test
testDismissed_onCreateKeyguardSurface_timeout()186     public void testDismissed_onCreateKeyguardSurface_timeout() throws Exception {
187         // Mocked KeyguardClient never handles the onCreateKeyguardSurface, so the operation
188         // times out, resulting in the view being dismissed.
189         doAnswer(answerVoid(Runnable::run)).when(mHandler)
190                 .postDelayed(any(Runnable.class), anyLong());
191 
192         mTestController.show(mServiceIntent);
193 
194         verifyViewDismissed(verifySurfaceReady());
195     }
196 
verifySurfaceReady()197     private SurfaceView verifySurfaceReady() throws Exception {
198         mTestableLooper.processAllMessages();
199         ArgumentCaptor<SurfaceView> captor = ArgumentCaptor.forClass(SurfaceView.class);
200         verify(mKeyguardSecurityContainer).addView(captor.capture());
201 
202         mTestableLooper.processAllMessages();
203         verify(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
204         return captor.getValue();
205     }
206 
verifyViewDismissed(SurfaceView v)207     private void verifyViewDismissed(SurfaceView v) throws Exception {
208         verify(mKeyguardSecurityContainer).removeView(v);
209         verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true, SecurityMode.Invalid);
210         assertThat(mContext.isBound(mComponentName)).isFalse();
211     }
212 }
213