• 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.os.Handler;
37 import android.os.RemoteException;
38 import android.testing.AndroidTestingRunner;
39 import android.testing.TestableLooper;
40 import android.testing.TestableLooper.RunWithLooper;
41 import android.testing.ViewUtils;
42 import android.view.SurfaceControlViewHost;
43 import android.view.SurfaceView;
44 import android.view.ViewGroup;
45 import android.widget.FrameLayout;
46 
47 import androidx.test.filters.SmallTest;
48 
49 import com.android.systemui.SysuiTestCase;
50 
51 import org.junit.After;
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.ArgumentCaptor;
56 import org.mockito.Mock;
57 import org.mockito.MockitoAnnotations;
58 
59 @RunWithLooper
60 @RunWith(AndroidTestingRunner.class)
61 @SmallTest
62 public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
63 
64     private static final int TARGET_USER_ID = KeyguardUpdateMonitor.getCurrentUser();
65 
66     private AdminSecondaryLockScreenController mTestController;
67     private ComponentName mComponentName;
68     private Intent mServiceIntent;
69     private TestableLooper mTestableLooper;
70     private ViewGroup mParent;
71 
72     @Mock
73     private Handler mHandler;
74     @Mock
75     private IKeyguardClient.Stub mKeyguardClient;
76     @Mock
77     private KeyguardSecurityCallback mKeyguardCallback;
78     @Mock
79     private KeyguardUpdateMonitor mUpdateMonitor;
80     @Mock
81     private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
82 
83     @Before
setUp()84     public void setUp() {
85         MockitoAnnotations.initMocks(this);
86 
87         mParent = spy(new FrameLayout(mContext));
88         ViewUtils.attachView(mParent);
89 
90         mTestableLooper = TestableLooper.get(this);
91         mComponentName = new ComponentName(mContext, "FakeKeyguardClient.class");
92         mServiceIntent = new Intent().setComponent(mComponentName);
93 
94         mContext.addMockService(mComponentName, mKeyguardClient);
95         // Have Stub.asInterface return the mocked interface.
96         when(mKeyguardClient.queryLocalInterface(anyString())).thenReturn(mKeyguardClient);
97         when(mKeyguardClient.asBinder()).thenReturn(mKeyguardClient);
98 
99         mTestController = new AdminSecondaryLockScreenController(
100                 mContext, mParent, mUpdateMonitor, mKeyguardCallback, mHandler);
101     }
102 
103     @After
tearDown()104     public void tearDown() {
105         ViewUtils.detachView(mParent);
106     }
107 
108     @Test
testShow()109     public void testShow() throws Exception {
110         doAnswer(invocation -> {
111             IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
112             callback.onRemoteContentReady(mSurfacePackage);
113             return null;
114         }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
115 
116         mTestController.show(mServiceIntent);
117 
118         verifySurfaceReady();
119         assertThat(mContext.isBound(mComponentName)).isTrue();
120     }
121 
122     @Test
testShow_dismissedByCallback()123     public void testShow_dismissedByCallback() throws Exception {
124         doAnswer(answerVoid(Runnable::run)).when(mHandler).post(any(Runnable.class));
125         doAnswer(invocation -> {
126             IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
127             callback.onDismiss();
128             return null;
129         }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
130 
131         mTestController.show(mServiceIntent);
132 
133         verifyViewDismissed(verifySurfaceReady());
134     }
135 
136     @Test
testHide()137     public void testHide() throws Exception {
138         // Show the view first, then hide.
139         doAnswer(invocation -> {
140             IKeyguardCallback callback = (IKeyguardCallback) invocation.getArguments()[1];
141             callback.onRemoteContentReady(mSurfacePackage);
142             return null;
143         }).when(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
144 
145         mTestController.show(mServiceIntent);
146         SurfaceView v = verifySurfaceReady();
147 
148         mTestController.hide();
149         verify(mParent).removeView(v);
150         assertThat(mContext.isBound(mComponentName)).isFalse();
151     }
152 
153     @Test
testHide_notShown()154     public void testHide_notShown() throws Exception {
155         mTestController.hide();
156         // Nothing should happen if trying to hide when the view isn't attached yet.
157         verify(mParent, never()).removeView(any(SurfaceView.class));
158     }
159 
160     @Test
testDismissed_onCreateKeyguardSurface_RemoteException()161     public void testDismissed_onCreateKeyguardSurface_RemoteException() throws Exception {
162         doThrow(new RemoteException()).when(mKeyguardClient)
163                 .onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
164 
165         mTestController.show(mServiceIntent);
166 
167         verifyViewDismissed(verifySurfaceReady());
168     }
169 
170     @Test
testDismissed_onCreateKeyguardSurface_timeout()171     public void testDismissed_onCreateKeyguardSurface_timeout() throws Exception {
172         // Mocked KeyguardClient never handles the onCreateKeyguardSurface, so the operation
173         // times out, resulting in the view being dismissed.
174         doAnswer(answerVoid(Runnable::run)).when(mHandler)
175                 .postDelayed(any(Runnable.class), anyLong());
176 
177         mTestController.show(mServiceIntent);
178 
179         verifyViewDismissed(verifySurfaceReady());
180     }
181 
verifySurfaceReady()182     private SurfaceView verifySurfaceReady() throws Exception {
183         mTestableLooper.processAllMessages();
184         ArgumentCaptor<SurfaceView> captor = ArgumentCaptor.forClass(SurfaceView.class);
185         verify(mParent).addView(captor.capture());
186 
187         mTestableLooper.processAllMessages();
188         verify(mKeyguardClient).onCreateKeyguardSurface(any(), any(IKeyguardCallback.class));
189         return captor.getValue();
190     }
191 
verifyViewDismissed(SurfaceView v)192     private void verifyViewDismissed(SurfaceView v) throws Exception {
193         verify(mParent).removeView(v);
194         verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true);
195         assertThat(mContext.isBound(mComponentName)).isFalse();
196     }
197 }
198