1 /*
2  * Copyright (C) 2017 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 android.view.WindowInsets.Type.ime;
20 import static android.view.WindowInsets.Type.systemBars;
21 
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.Mockito.never;
24 import static org.mockito.Mockito.reset;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
27 
28 import android.graphics.Insets;
29 import android.testing.AndroidTestingRunner;
30 import android.testing.TestableLooper;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.view.WindowInsets;
34 import android.view.WindowInsetsController;
35 import android.widget.FrameLayout;
36 
37 import androidx.test.filters.SmallTest;
38 
39 import com.android.systemui.SysuiTestCase;
40 
41 import org.junit.Before;
42 import org.junit.Rule;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.mockito.Mock;
46 import org.mockito.junit.MockitoJUnit;
47 import org.mockito.junit.MockitoRule;
48 
49 @SmallTest
50 @RunWith(AndroidTestingRunner.class)
51 @TestableLooper.RunWithLooper()
52 public class KeyguardSecurityContainerTest extends SysuiTestCase {
53     private static final int SCREEN_WIDTH = 1600;
54     private static final int FAKE_MEASURE_SPEC =
55             View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH, View.MeasureSpec.EXACTLY);
56 
57     @Rule
58     public MockitoRule mRule = MockitoJUnit.rule();
59 
60     @Mock
61     private WindowInsetsController mWindowInsetsController;
62 
63     @Mock
64     private KeyguardSecurityViewFlipper mSecurityViewFlipper;
65 
66     private KeyguardSecurityContainer mKeyguardSecurityContainer;
67 
68     @Before
setup()69     public void setup() {
70         // Needed here, otherwise when mKeyguardSecurityContainer is created below, it'll cache
71         // the real references (rather than the TestableResources that this call creates).
72         mContext.ensureTestableResources();
73         FrameLayout.LayoutParams securityViewFlipperLayoutParams = new FrameLayout.LayoutParams(
74                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
75 
76         when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
77         when(mSecurityViewFlipper.getLayoutParams()).thenReturn(securityViewFlipperLayoutParams);
78         mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
79         mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
80         mKeyguardSecurityContainer.addView(mSecurityViewFlipper, new ViewGroup.LayoutParams(
81                 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
82     }
83 
84     @Test
onMeasure_usesHalfWidthWithOneHandedModeEnabled()85     public void onMeasure_usesHalfWidthWithOneHandedModeEnabled() {
86         mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */true);
87 
88         int halfWidthMeasureSpec =
89                 View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH / 2, View.MeasureSpec.EXACTLY);
90         mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
91 
92         verify(mSecurityViewFlipper).measure(halfWidthMeasureSpec, FAKE_MEASURE_SPEC);
93     }
94 
95     @Test
onMeasure_usesFullWidthWithOneHandedModeDisabled()96     public void onMeasure_usesFullWidthWithOneHandedModeDisabled() {
97         mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */false);
98 
99         mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
100         verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
101     }
102 
103     @Test
onMeasure_respectsViewInsets()104     public void onMeasure_respectsViewInsets() {
105         int imeInsetAmount = 100;
106         int systemBarInsetAmount = 10;
107 
108         mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */false);
109 
110         Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
111         Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
112 
113         WindowInsets insets = new WindowInsets.Builder()
114                 .setInsets(ime(), imeInset)
115                 .setInsetsIgnoringVisibility(systemBars(), systemBarInset)
116                 .build();
117 
118         // It's reduced by the max of the systembar and IME, so just subtract IME inset.
119         int expectedHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
120                 SCREEN_WIDTH - imeInsetAmount, View.MeasureSpec.EXACTLY);
121 
122         mKeyguardSecurityContainer.onApplyWindowInsets(insets);
123         mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
124         verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, expectedHeightMeasureSpec);
125     }
126 
127     @Test
onMeasure_respectsViewInsets_largerSystembar()128     public void onMeasure_respectsViewInsets_largerSystembar() {
129         int imeInsetAmount = 0;
130         int systemBarInsetAmount = 10;
131 
132         mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */false);
133 
134         Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
135         Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
136 
137         WindowInsets insets = new WindowInsets.Builder()
138                 .setInsets(ime(), imeInset)
139                 .setInsetsIgnoringVisibility(systemBars(), systemBarInset)
140                 .build();
141 
142         int expectedHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
143                 SCREEN_WIDTH - systemBarInsetAmount, View.MeasureSpec.EXACTLY);
144 
145         mKeyguardSecurityContainer.onApplyWindowInsets(insets);
146         mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
147         verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, expectedHeightMeasureSpec);
148     }
149 
setupForUpdateKeyguardPosition(boolean oneHandedMode)150     private void setupForUpdateKeyguardPosition(boolean oneHandedMode) {
151         mKeyguardSecurityContainer.setOneHandedMode(oneHandedMode);
152         mKeyguardSecurityContainer.setOneHandedModeLeftAligned(true, false);
153 
154         mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
155         mKeyguardSecurityContainer.layout(0, 0, SCREEN_WIDTH, SCREEN_WIDTH);
156 
157         // Clear any interactions with the mock so we know the interactions definitely come from the
158         // below testing.
159         reset(mSecurityViewFlipper);
160     }
161 
162     @Test
setIsLeftAligned_movesKeyguard()163     public void setIsLeftAligned_movesKeyguard() {
164         setupForUpdateKeyguardPosition(/* oneHandedMode= */ true);
165 
166         mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
167                 /* leftAligned= */false, /* animate= */false);
168         verify(mSecurityViewFlipper).setTranslationX(
169                 mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
170 
171         mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
172                 /* leftAligned= */true, /* animate= */false);
173         verify(mSecurityViewFlipper).setTranslationX(0.0f);
174     }
175 
176     @Test
setIsLeftAligned_doesntMoveTwoHandedKeyguard()177     public void setIsLeftAligned_doesntMoveTwoHandedKeyguard() {
178         setupForUpdateKeyguardPosition(/* oneHandedMode= */ false);
179 
180         mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
181                 /* leftAligned= */false, /* animate= */false);
182         verify(mSecurityViewFlipper, never()).setTranslationX(anyInt());
183 
184         mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
185                 /* leftAligned= */true, /* animate= */false);
186         verify(mSecurityViewFlipper, never()).setTranslationX(anyInt());
187     }
188 }
189